验证JAXB,但空格不被忽略

时间:2009-07-11 03:46:21

标签: java xml xml-serialization jaxb

一些代码段。

执行jaxb unmarshaling的java编码。非常简单,在网上复制了教程。

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())

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:2)

我建议编写一个非常简单的XSLT转换来从导致问题的特定元素中去掉空内容(例如只有HashLine元素)。然后在通过JAXB传递数据之前,使用TransformerFactory,Transformer等进行处理,然后使用XSLT转换“清理”数据。您可以在XSLT中添加各种清理逻辑,以便在源XML中找到其他非JAXB友好结构。

相关问题