[英]How can I validate my XML using a schema, reading only one object/element at a time by JAXB's XMLStreamReader?
下面的代碼可以正確地從 stream 一次解組 XML 一個 object。
但是當我取消注釋unmarshaller.setSchema(schema)
行時,程序會拋出異常:
[org.xml.sax.SAXParseException:cvc-elt.1:找不到元素“訂閱者”的聲明。]
我已經使用javax.xml.validation.Validator
class 驗證了 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();
}
}
我的模式訂閱者的摘錄。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
的 class 。 如果你給它一個帶有<Subscribers>
根元素的 XML 文檔,它知道它必須解組到SubscriberType
的 class 。 但是,如果您給它一個帶有<Subscriber>
根元素的 XML 文檔,它通常不會在 XJC 生成的ObjectFactory
class 中找到此元素定義。 但是,由於您使用了帶有第二個參數的unmarshal
組方法,即您期望的 class,因此您告訴解組器它應該將其輸入解釋為SubscriberType
。 結果將是一個空的SubscriberType
實例。
現在,由於您正在逐一迭代<Subscriber>
元素(至少我認為這是您的意思),對於解組器來說,它似乎正在接收 XML 文檔,並將其作為根元素。 它不會抱怨找不到該定義,因為您已經完成了使用 class 參數找出類型的任務。 但是,當您附加一個模式進行驗證時,事情就會崩潰。 驗證器不知道您在<Subscribers>
元素中。 它期待完整的 XML 文檔。 因此它會為<Subscriber>
尋找元素聲明,但結果為空,因為該元素僅在復雜類型中定義。 它不是一個全局元素定義(即模式根下的一個)。
所以,這里有兩件事要做。 一種是定義元素<Subscriber>
如上所示,然后在您的復雜類型中引用它。 另一種是將您的解組調用更改為unmarshal(streamReader, SubscriberInformation.class)
以獲取 object 的正確類型。 還要注意無限循環或不正確的解組,因為您對streamReader.next()
的調用處於條件並且可能不會觸發。
編寫帶有 JAXB 的模式需要一定的風格。 一般來說,最好全局定義元素,然后引用它們。 如果元素絕對必須保持封裝在那里,則僅在復雜類型中本地定義元素。
對不起,冗長的回答,我不是很清醒:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.