Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用模式验证XML,通过JAXB'一次只读取一个对象/元素;XMLStreamReader?_Java_Xml_Jaxb_Stax - Fatal编程技术网

Java 如何使用模式验证XML,通过JAXB'一次只读取一个对象/元素;XMLStreamReader?

Java 如何使用模式验证XML,通过JAXB'一次只读取一个对象/元素;XMLStreamReader?,java,xml,jaxb,stax,Java,Xml,Jaxb,Stax,下面的代码可以正确地从流中一次解组一个对象的XML 但是当我取消注释unmarshaller.setSchema(schema)行时,程序会抛出一个异常: [org.xml.sax.SAXParseException:cvc elt.1:找不到元素'Subscriber'的声明。] 我已经使用javax.XML.validation.Validator类验证了XML,但我的目标是同时验证和解组,每次一个元素 这是我当前的代码: SchemaFactory sf = SchemaFactory.n

下面的代码可以正确地从流中一次解组一个对象的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();
    }
}
SchemaFactory sf=SchemaFactory.newInstance(xmlstants.W3C\u XML\u SCHEMA\u NS\u URI);
Schema Schema=sf.newSchema(新文件(“/Path to xsd”);
XMLInputFactory inputFactory=XMLInputFactory.newInstance();
XMLStreamReader streamReader=inputFactory.createXMLStreamReader(新文件读取器(“/Path to xml”);
JAXBContext JAXBContext=JAXBContext.newInstance(SubscriberType.class);
Unmarshaller Unmarshaller=jaxbContext.createUnmarshaller();
//解组器。设置模式(模式);
streamReader.nextTag();
require(XMLStreamConstants.START_元素,null,“订阅者”);
streamReader.nextTag();
while(streamReader.getEventType()==XMLStreamConstants.START\u元素){
JAXBElement pt=unmarshaller.unmarshal(streamReader,SubscriberType.class);
//对解组对象pt…store to db ect执行一些操作。
if(streamReader.getEventType()==XMLStreamConstants.CHARACTERS){
streamReader.next();
}
}
my schema 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
的类。如果要给它一个带有
根元素的XML文档,它知道它必须解组到
SubscriberType
的类。但是,如果您给它一个带有
根元素的XML文档,它通常在XJC生成的
对象工厂
类中找不到该元素定义。但是,由于您使用了
unmarshal
方法,该方法接受第二个参数,即您所期望的类,因此您已经告诉unmarshaller它应该将其输入解释为
SubscriberType
。结果将是一个空的
SubscriberType
实例

现在,由于您正在逐个迭代
元素(至少我认为您的意思是这样做的),对于解组器来说,它似乎正在接收作为根元素的XML文档。它不会抱怨找不到那个定义,因为你已经用class参数把计算类型的任务去掉了。但是,当您附加一个用于验证的模式时,事情就崩溃了。验证器不知道您在
元素中。它需要一个完整的XML文档。因此,它将查找
的元素声明,但结果为空,因为该元素仅在复杂类型中定义。它不是全局元素定义(即模式根下的定义)

所以,这里有两件事要做。一种是如上所示定义元素
,然后在复杂类型中引用它。另一种方法是将unmarshal调用更改为
unmarshal(streamReader,SubscriberInformation.class)
,以获取正确类型的对象。还要注意无限循环或不正确的解组,因为对
streamReader.next()
的调用处于某种状态,可能不会触发

使用JAXB编写模式需要某种风格。通常,最好全局定义元素,然后引用它们。仅在复杂类型中本地定义一个元素,前提是它必须保持封装状态


对不起,我的回答太冗长了,我不是很清醒:)

你能给我们看看模式文件吗?基本上只验证XML的摘录,而不是整个文档。您是否使用验证器验证了整个文档?如果模式中唯一的元素声明是针对根节点的,那么他找不到“订阅者”的声明是有意义的。您所说的有意义…我将编辑模式并尝试一下。