Java 正在验证JAXB,但不忽略空白

Java 正在验证JAXB,但不忽略空白,java,xml,xml-serialization,jaxb,Java,Xml,Xml Serialization,Jaxb,一些代码片段 执行jaxb解组的java编码。非常简单,从在线教程中复制而来 JAXBContext jc = JAXBContext.newInstance( "xmlreadtest" ); Unmarshaller u = jc.createUnmarshaller(); // setting up for validation. SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SC

一些代码片段

执行jaxb解组的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>
我已确认错误来自该元素

它加载良好,无需验证。但我需要使用验证,因为我将对应用程序进行重大更改和添加,并且我必须确保所有内容都被正确封送/取消封送

如果我将complexType更改为包含带有xs:string扩展名的simpleContext,它也可以正常工作。但是我从世界各地的实体那里得到这个问题,其中有很多,amd在很多xsd文件中。因此,仅仅为了解决这个问题而将xml文档中的每个元素都基于xs:string是不可行的

事件尽管j2se 6正在使用ApacheXerces的SchemaFactory,但它似乎不接受来自xerces的“忽略空白”特性。(即schemaFactory.setFeature())

在验证之前,您可以使用以下方法过滤空字符块:

这可用于包装您的输入:

// 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

我建议编写一个非常简单的XSLT转换,从导致问题的特定元素(例如,仅HashLine元素)中去除空内容。然后在通过JAXB传递数据之前,使用TransformerFactory、Transformer等进行处理,这将使用XSLT转换“清理”数据。对于在源XML中发现其他不支持JAXB的结构的情况,您可以在XSLT中添加一些清理逻辑。

我不认为文档不支持JAXB,而是不支持验证。你可能是对的,最好针对特定的元素。我想您可以用DOM/XPath做一些类似的事情,但它没有使用XSLT那么优雅。是的,我认为在这种情况下,声明式方法永远都不会比命令式方法更完美。如果XML文档不符合模式,则需要在将其传递给验证器之前进行修复。XSLT擅长于这类事情。提供的两个答案都有效。但是我首先尝试了另一个答案,因为它包含了一些很好的示例代码。后来,出于各种原因,我转而使用这种解决方案。
[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.]
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