下面的代码可以正常地从一个对象的流中解析XML。
但是当我取消评论unmarshaller.setSchema(schema)
行时,该程序会抛出异常:
[org.xml.sax.SAXParseException:cvc-elt.1:找不到元素'Subscriber'的声明。]
我已经使用javax.xml.validation.Validator
类验证了XML,但我的目标是同时验证和解组,一次一个元素。
这是我目前的代码:
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(new File("/Path to xsd"));
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
XMLStreamReader streamReader = inputFactory.createXMLStreamReader(new FileReader("/Path to xml"));
JAXBContext jaxbContext = JAXBContext.newInstance(SubscriberType.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
//unmarshaller.setSchema(schema);
streamReader.nextTag();
streamReader.require(XMLStreamConstants.START_ELEMENT, null, "Subscribers");
streamReader.nextTag();
while (streamReader.getEventType() == XMLStreamConstants.START_ELEMENT) {
JAXBElement<SubscriberType> pt = unmarshaller.unmarshal(streamReader, SubscriberType.class);
//do something with the unmarshalled object pt...store to db ect.
if (streamReader.getEventType() == XMLStreamConstants.CHARACTERS) {
streamReader.next();
}
}
我的架构subscriber.xsd的摘录:
<?xml version="1.0" encoding="UTF-8" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="unqualified"
attributeFormDefault="unqualified">
<xsd:element name="Subscribers" type="SubscriberType" />
<xsd:complexType name="SubscriberType">
<xsd:sequence>
<xsd:element name="Subscriber"
type="SubscriberInformation"
minOccurs="1"
maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
答案 0 :(得分:1)
尝试使用这样的架构:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="unqualified" attributeFormDefault="unqualified">
<xsd:element name="Subscribers" type="SubscriberType"/>
<xsd:element name="Subscriber" type="SubscriberInformation" />
<xsd:complexType name="SubscriberType">
<xsd:sequence>
<xsd:element ref="Subscriber" minOccurs="1" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
我相信你的架构会发生这样的事情:JAXB上下文知道SubscriberType
和SubscriberInformation
的类。如果你要给它一个带有<Subscribers>
根元素的XML文档,它就知道它必须为SubscriberType
的类解组。但是如果你给它一个带有<Subscriber>
根元素的XML文档,它通常不会在XJC生成的ObjectFactory
类中找到这个元素定义。但是既然你已经使用了unmarshal
方法来接受第二个参数,即你期望的类,你已经告诉unmarshaller它应该将它的输入解释为SubscriberType
。结果将是一个空的SubscriberType
实例。
现在,既然你逐个遍历<Subscriber>
个元素(至少这是我收集你的意思),对于unmarshaller来说,似乎它正在接收带有该元素的XML文档作为根元素。它不会抱怨没有找到那个定义,因为你已经完成了使用类参数计算类型的任务。但是,当您附加架构进行验证时,事情就会崩溃。验证器不知道您在<Subscribers>
元素内。它期待一个完整的XML文档。因此,它会查找<Subscriber>
的元素声明,但会显示为空,因为该元素仅在复杂类型中定义。它不是全局元素定义(即模式根目录下的定义)。
所以,这里有两件事要做。一种是定义元素<Subscriber>
,如上所示,然后在复杂类型中引用它。另一种方法是将您的解组调用更改为unmarshal(streamReader, SubscriberInformation.class)
以获取正确类型的对象。同时注意无限循环或不正确的解组,因为您对streamReader.next()
的调用处于某种状态并且可能无法触发。
使用JAXB编写模式需要一定的风格。通常,最好全局定义元素,然后引用它们。只有在绝对必须保持封装的情况下才在复杂类型中本地定义元素。
对不起啰嗦的答案,我不太清醒:)