2009-07-11 82 views
4

一些代碼片段。驗證JAXB,但空白不被忽略

java編碼做jaxb解組。非常簡單,在線教程複製出來。

JAXBContext jc = JAXBContext.newInstance("xmlreadtest"); 
Unmarshaller u = jc.createUnmarshaller(); 

// setting up for validation. 
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
StreamSource schemaSource = new StreamSource(ReadXml.class.getResource("level.xsd").getFile()); 
Schema schema = schemaFactory.newSchema(schemaSource); 
u.setSchema(schema); 

// parsing the xml 
URL url = ReadXml.class.getResource("level.xml"); 
Source sourceRoot = (Source)u.unmarshal(url); 

xml文件中的問題元素。該元素只包含可忽略的空白。它嚴重格式化爲,正好如何在文件中找到它。

<HashLine _id='FI6' 
ppLine='1' 
origLine='1' 
origFname='level.cpp'> 
</HashLine> 

描述此元素的xsd元素。

<xs:element name="HashLine"> 
    <xs:complexType> 
    <xs:attribute name="origLine" type="xs:NMTOKEN" use="required" /> 
    <xs:attribute name="origFname" type="xs:string" use="required" /> 
    <xs:attribute name="_id" type="xs:ID" use="required" /> 
    <xs:attribute name="ppLine" type="xs:NMTOKEN" use="required" /> 
    </xs:complexType> 
</xs:element> 

誤差

[org.xml.sax.SAXParseException: cvc-complex-type.2.1: Element 'HashLine' must have no character or element information item [children], because the type's content type is empty.] 

我已經驗證錯誤是來自該元素的到來。

它加載沒有驗證罰款。但是我需要使用驗證,因爲我將對應用程序進行大量更改和添加,並且必須確保所有內容都能夠正確編組/解組。

如果我將complexType更改爲包含具有xs:string擴展名的simpleContext,它也可以正常工作。但是我從各個實體那裏得到了這個問題,其中有很多xsd文件。因此,爲了解決這個問題,將xml文檔中的每個元素都放在xs:string中是不可行的。

儘管j2se 6的事件使用apache-xerces中的SchemaFactory,但似乎並未接受來自xerces的'ignore-whitespace'功能。 (即schemaFactory.setFeature())

回答

4

您可以使用StAX API使用EventFilter空字符塊過濾掉驗證之前:

class WhitespaceFilter implements EventFilter { 
    @Override 
    public boolean accept(XMLEvent event) { 
    return !(event.isCharacters() && ((Characters) event) 
     .isWhiteSpace()); 
    } 
} 

這可以用來包裹你的輸入:

// strip unwanted whitespace 
XMLInputFactory inputFactory = XMLInputFactory.newInstance(); 
XMLEventReader eventReader = inputFactory 
    .createXMLEventReader(ReadXml.class.getResourceAsStream("level.xml")); 
eventReader = inputFactory.createFilteredReader(eventReader, 
    new WhitespaceFilter()); 

// parsing the xml 
Source sourceRoot = (Source) unmarshaller.unmarshal(eventReader); 

//TODO: proper error + stream handling 
2

我會建議編寫一個非常簡單的XSLT轉換來從那些導致問題的特定元素(例如,僅HashLine元素)中去掉空白內容。然後在通過JAXB傳遞數據之前進行一個處理步驟,方法是使用TransformerFactory,Transformer等等,它使用XSLT轉換「清除」數據。如果您在源XML中找到其他非JAXB友好結構,則可以在XSLT中添加各種清理邏輯。

+0

我不認爲它是如此之多,該文件不是JAXB友好的,因爲它不是驗證友好的。針對特定元素的定位可能會更好。我想你可以用DOM/XPath做類似的事情,但不會像使用XSLT那樣優雅。 – McDowell 2009-07-11 11:21:43