簡體   English   中英

JAXB綁定以刪除propOrder

[英]JAXB binding to remove propOrder

我寫了一個XSD:

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
            targetNamespace="http://api.synthesys/models/generated/simple/chat"
            xmlns:drsc="http://api.synthesys/models/generated/simple/chat"
            xmlns:simplify="http://jaxb2-commons.dev.java.net/basic/simplify"
            jaxb:extensionBindingPrefixes="simplify"
            jaxb:version="2.1">
    <xsd:element name="conversation">
        <xsd:complexType>
            <xsd:sequence>

                <xsd:element name="start-time" type="xsd:dateTime" minOccurs="1" maxOccurs="1"/>


                <xsd:choice minOccurs="0" maxOccurs="unbounded">

                    <!-- for code generation, allowing direct and distinct access to the messages and events -->
                    <xsd:annotation>
                        <xsd:appinfo>
                            <simplify:as-element-property/>
                        </xsd:appinfo>
                    </xsd:annotation>

                    <!--messages-->
                    <xsd:element name="message">
                        <xsd:complexType>
                            <xsd:sequence>
                                <xsd:element name="author" minOccurs="1" maxOccurs="1" type="xsd:string"/>
                                <xsd:element name="text" minOccurs="1" maxOccurs="1" type="xsd:string"/>
                            </xsd:sequence>
                        </xsd:complexType>
                    </xsd:element>

                    <!--room events: entering or exiting the room-->
                    <xsd:element name="event">
                        <xsd:complexType>
                            <xsd:sequence>
                                <xsd:element name="who" minOccurs="1" maxOccurs="1" type="xsd:string"/>
                                <xsd:element name="what" minOccurs="1" maxOccurs="1" type="xsd:string"/>
                            </xsd:sequence>
                        </xsd:complexType>
                    </xsd:element>
                </xsd:choice>

                <!--end time millis-->
                <xsd:element name="end-time" type="xsd:dateTime" minOccurs="1" maxOccurs="1"/>

            </xsd:sequence>

        </xsd:complexType>
    </xsd:element>
</xsd:schema>

並且我編寫了一個示例XML文件:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<mine:conversation xmlns:mine="http://api.synthesys/models/generated/simple/chat">
    <start-time>2017-09-10T12:00:00.000Z</start-time>
    <event>
        <who>John</who>
        <what>entered the room</what>
    </event>
    <message>
        <author>John</author>
        <text>hello</text>
    </message>
    <event>
        <who>Jane</who>
        <what>entered the room</what>
    </event>
    <message>
        <author>Jane</author>
        <text>goodbye, John</text>
    </message>
    <event>
        <who>Jane</who>
        <what>left the room</what>
    </event>
    <event>
        <who>John</who>
        <what>left the room</what>
    </event>
    <end-time>2017-09-10T12:01:00.000Z</end-time>
</mine:conversation>

借助maven-jaxb2-plugin我已經能夠從這種模式生成一個類,如下所示:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "startTime",
    "messages",
    "events",
    "endTime"
})
@XmlRootElement(name = "conversation")
public class Conversation {

    @XmlElement(name = "start-time", required = true, type = String.class)
    @XmlJavaTypeAdapter(Adapter1 .class)
    @XmlSchemaType(name = "dateTime")
    protected XMLGregorianCalendar startTime;
    @XmlElement(name = "message")
    protected List<Conversation.Message> messages;
    @XmlElement(name = "event")
    protected List<Conversation.Event> events;
    @XmlElement(name = "end-time", required = true, type = String.class)
    @XmlJavaTypeAdapter(Adapter1 .class)
    @XmlSchemaType(name = "dateTime")
    protected XMLGregorianCalendar endTime; 

問題是,當我嘗試使用JAXB像這樣解組我的示例xml文件時:

class MarshalUnmarshalTest extends Specification {
    def "test"(){
        setup:
        SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        JAXBContext context = JAXBContext.newInstance(synthesys.api.models.generated.simple.chat.Conversation.class)
        Marshaller marshaller = context.createMarshaller()
        Unmarshaller unmarshaller = context.createUnmarshaller()
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        context.generateSchema(new StructuredDataUtils.StructuredDataSchemaOutputResolver(bos));
        Schema schema = sf.newSchema(new StreamSource(new ByteArrayInputStream(bos.toByteArray())));
        marshaller.setSchema(schema)
        unmarshaller.setSchema(schema)

        File input = new File("src/test/resources/data/genericChat/simple-valid.xml")


        when:
        def object = unmarshaller.unmarshal(input.newInputStream())

        then:
        object instanceof synthesys.api.models.generated.simple.chat.Conversation
    }
}

我收到此錯誤:

    javax.xml.bind.UnmarshalException
 - with linked exception:
[org.xml.sax.SAXParseException; lineNumber: 8; columnNumber: 14; cvc-complex-type.2.4.a: Invalid content was found starting with element 'message'. One of '{event, end-time}' is expected.]
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.createUnmarshalException(AbstractUnmarshallerImpl.java:335)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.createUnmarshalException(UnmarshallerImpl.java:563)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:249)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:214)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:157)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:204)
    at synthesys.api.models.generated.standard.chat.MarshalUnmarshalTest.test(MarshalUnmarshalTest.groovy:31)
Caused by: org.xml.sax.SAXParseException; lineNumber: 8; columnNumber: 14; cvc-complex-type.2.4.a: Invalid content was found starting with element 'message'. One of '{event, end-time}' is expected.
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:203)
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:134)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:437)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:368)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:325)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator$XSIErrorReporter.reportError(XMLSchemaValidator.java:458)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.reportSchemaError(XMLSchemaValidator.java:3237)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleStartElement(XMLSchemaValidator.java:1796)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.startElement(XMLSchemaValidator.java:746)
    at com.sun.org.apache.xerces.internal.jaxp.validation.ValidatorHandlerImpl.startElement(ValidatorHandlerImpl.java:570)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.ValidatingUnmarshaller.startElement(ValidatingUnmarshaller.java:86)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:163)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:509)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:379)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2786)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:606)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:117)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:848)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:649)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:243)
    ... 4 more

真正讓我感到沮喪的是,此示例文件在使用xmllint --noout --schema path/to/schema.xsd path/to/sample.xml時進行了驗證。 在我看來,主要的問題是,生成的Conversation類定義了一個propOrder ,它比模式實際的限制更多。

誰能指出我如何配置簡化插件以不生成此propOrder? 或者,我如何才能利用綁定來消除該限制? 我確實想保持當前行為,其中我生成的類同時具有List<Message> messages屬性和List<Event> events屬性,而不是單個List<Object> messagesOrEvents

免責聲明:我是JAXB2簡化插件JAXB2注釋插件的作者

問題是簡化屬性(就像您所做的那樣)可以有效地更改XML的結構。 它不再是messageeventend-time的任何順序。 簡化后是一些固定的順序。 這就是您為Java模型中易於使用的結構所付出的代價。

誰能指出我如何配置簡化插件以不生成此propOrder?

不會propOrder插件不會生成propOrder ,而XJC會生成。 simple插件僅將異構屬性“轉換”為幾個簡單的同類屬性。 它與propOrder

它可以自定義生成@XmlType使用注釋JAXB2注釋插件 ,但我不肯定是否propOrder是問題。 老實說,我對您在元素順序方面遇到問題感到驚訝。 我一直以為JAXB在解組時並不關心順序。

如果需要,請在https://github.com/highsource/maven-jaxb2-plugin-support/tree/master/s/simplify下發布您的最小示例項目,我來看一下。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM