简体   繁体   English

JAXB绑定以删除propOrder

[英]JAXB binding to remove propOrder

I have written an XSD: 我写了一个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>

and I have written a sample XML file: 并且我编写了一个示例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>

And with the maven-jaxb2-plugin I have been able to generate a class from this schema like this: 借助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; 

The problem is that when I try to use JAXB to unmarshall my sample xml file like this: 问题是,当我尝试使用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
    }
}

I get this error: 我收到此错误:

    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

What's really frustrating to me is that this sample file validates when using xmllint --noout --schema path/to/schema.xsd path/to/sample.xml . 真正让我感到沮丧的是,此示例文件在使用xmllint --noout --schema path/to/schema.xsd path/to/sample.xml时进行了验证。 It seems to me that the main issue is that the generated Conversation class defines a propOrder that is more restrictive than the schema actually is. 在我看来,主要的问题是,生成的Conversation类定义了一个propOrder ,它比模式实际的限制更多。

Can anyone point me to how I can configure the simplify plugin to not generate this propOrder? 谁能指出我如何配置简化插件以不生成此propOrder? Or how I can otherwise leverage bindings to remove that restriction? 或者,我如何才能利用绑定来消除该限制? I do want to maintain the current behavior where my generated class has both a List<Message> messages property and a List<Event> events property, rather than a single List<Object> messagesOrEvents 我确实想保持当前行为,其中我生成的类同时具有List<Message> messages属性和List<Event> events属性,而不是单个List<Object> messagesOrEvents

Disclaimer: I am the author of the JAXB2 Simplify Plugin and JAXB2 Annotate Plugin . 免责声明:我是JAXB2简化插件JAXB2注释插件的作者

The problem is that simplifying the property (like you did) effectively changes the structure of the XML. 问题是简化属性(就像您所做的那样)可以有效地更改XML的结构。 It's no longer message , event , end-time in any order. 它不再是messageeventend-time的任何顺序。 It's some fixed order after the simplification. 简化后是一些固定的顺序。 That's the price you pay for the easier-to-use structure in the Java model. 这就是您为Java模型中易于使用的结构所付出的代价。

Can anyone point me to how I can configure the simplify plugin to not generate this propOrder? 谁能指出我如何配置简化插件以不生成此propOrder?

No. The simplify plugin does not generate propOrder , XJC does. 不会propOrder插件不会生成propOrder ,而XJC会生成。 The simplify plugin only "converts" a heterogeneous property into several simple homogeneous properties. simple插件仅将异构属性“转换”为几个简单的同类属性。 It has nothing to do with propOrder . 它与propOrder

It is possible to customize the generated @XmlType annotation using the JAXB2 Annotate Plugin , but I'm not quite sure if propOrder is the problem. 它可以自定义生成@XmlType使用注释JAXB2注释插件 ,但我不肯定是否propOrder是问题。 To be honest I am somehow surprized that you have problems with the order of elements. 老实说,我对您在元素顺序方面遇到问题感到惊讶。 I always thought JAXB did not care about the order when unmarshalling. 我一直以为JAXB在解组时并不关心顺序。

If you want, please post your minimal sample project under https://github.com/highsource/maven-jaxb2-plugin-support/tree/master/s/simplify , I will take a look. 如果需要,请在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