我写了一个 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
类定义的 apropOrder
比实际的模式更具限制性。
谁能指出我如何配置简化插件以不生成此 propOrder?或者我如何才能利用绑定来消除该限制?我确实想保持当前行为,其中我生成的类同时具有List<Message> messages
属性和List<Event> events
属性,而不是单个List<Object> messagesOrEvents