gpt4 book ai didi

java - 如何使用模式验证我的 XML,JAXB 的 XMLStreamReader 一次只读取一个对象/元素?

转载 作者:数据小太阳 更新时间:2023-10-29 02:42:19 25 4
gpt4 key购买 nike

下面的代码可以正确地一次从一个对象的流中解码 XML。

但是当我取消对 unmarshaller.setSchema(schema) 行的注释时,程序会抛出异常:

[org.xml.sax.SAXParseException: cvc-elt.1: Cannot find the declaration of element '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>

最佳答案

尝试使用这样的架构:

<?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 文档然而,它通常不会在 ObjectFactory 中找到此元素定义。 XJC 生成的类。但是既然你已经使用了 unmarshal带有第二个参数的方法,即您期望的类,您已经告诉解码器它应该将其输入解释为 SubscriberType .结果将为空 SubscriberType实例。

现在,由于您正在遍历 <Subscriber>一个接一个的元素(至少这是我收集到的你打算做的),对于解码器来说,它似乎正在接收以它作为根元素的 XML 文档。它不会提示找不到该定义,因为您已经完成了通过类参数找出类型的任务。但是,当您附加一个用于验证的模式时,事情就崩溃了。 validator 不知道你在 <Subscribers> 中元素。它需要一个完整的 XML 文档。所以它会去寻找 <Subscriber> 的元素声明。但结果是空的,因为该元素仅在复杂类型中定义。它不是全局元素定义(即模式根下的元素定义)。

所以,这里有两件事要做。一种是定义元素<Subscriber>如上所示,然后在您的复杂类型中引用它。另一个是将您的解码调用更改为 unmarshal(streamReader, SubscriberInformation.class)返回正确类型的对象。还要注意无限循环或不正确的解码,因为您调用了 streamReader.next()处于某种状态,可能不会开火。

编写带有 JAXB 的模式需要特定的风格。一般来说,最好全局定义元素,然后引用它们。如果绝对必须在复杂类型中保持封装,则只在本地定义一个元素。

抱歉啰嗦的回答,我不是很清醒:)

关于java - 如何使用模式验证我的 XML,JAXB 的 XMLStreamReader 一次只读取一个对象/元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7096626/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com