JAXB привязка для удаления 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

1 ответ

Отказ от ответственности: я являюсь автором плагина JAXB2 Simplify и плагина JAXB2 Annotate.

Проблема в том, что упрощение свойства (как вы это сделали) эффективно меняет структуру XML. Это больше не message, event, end-time в любом порядке. Это некоторый фиксированный порядок после упрощения. Это цена, которую вы платите за более простую в использовании структуру в модели Java.

Может кто-нибудь указать мне, как я могу настроить плагин упрощения, чтобы не генерировать этот propOrder?

Нет. Плагин упрощения не генерирует propOrderXJC делает. Плагин упрощения только "преобразовывает" гетерогенное свойство в несколько простых однородных свойств. Это не имеет ничего общего с propOrder,

Можно настроить сгенерированный @XmlType аннотации с использованием плагина Annotate JAXB2, но я не совсем уверен, если propOrder это проблема. Если честно, я как-то удивлен, что у вас проблемы с порядком элементов. Я всегда думал, что JAXB не заботился о порядке, когда он отменял.

Если вы хотите, пожалуйста, опубликуйте ваш минимальный пример проекта в https://github.com/highsource/maven-jaxb2-plugin-support/tree/master/s/simplify, я посмотрю.

Другие вопросы по тегам