【问题标题】:Validation fails when writing XML with Woodstox / Stax2使用 Woodstox / Stax2 编写 XML 时验证失败
【发布时间】:2016-09-15 00:57:48
【问题描述】:

我在使用带有 Woodstox 和 Stax2 的 XSD 模式进行 XML 验证时遇到问题。即使 XML 数据符合架构,验证也会失败。

令人惊讶的是,验证问题仅在写入 XML(使用 XMLStreamWriter2)时出现,而不是在读取 XML(使用 XMLStreamReader2)时出现。

我构建了一个小示例来重现和隔离错误。 基本上,它只是将 XML 从文件读取到 XMLStreamReader2(使用 XSD 模式验证),然后将其复制到 XMLStreamWriter2(也使用相同的 XSD 验证)。

现在,这会因 writer 的验证错误而失败。如果我在 writer 上停用验证,一切都会顺利进行,并且 writer 会提供完全符合 XML 的内容。

代码如下:

import com.ctc.wstx.stax.WstxInputFactory;
import com.ctc.wstx.stax.WstxOutputFactory;
import org.codehaus.stax2.XMLStreamReader2;
import org.codehaus.stax2.XMLStreamWriter2;
import org.codehaus.stax2.validation.XMLValidationSchema;
import org.codehaus.stax2.validation.XMLValidationSchemaFactory;

import javax.xml.stream.XMLStreamException;
import java.io.InputStream;
import java.io.StringWriter;

public class Converter {

    public static void main(String... args) throws XMLStreamException {

        InputStream reader = Converter.class.getClassLoader().getResourceAsStream("test.xml");
        StringWriter writer = new StringWriter();

        XMLValidationSchema schema = XMLValidationSchemaFactory.newInstance(XMLValidationSchema.SCHEMA_ID_W3C_SCHEMA)
                .createSchema(Converter.class.getClassLoader().getResourceAsStream("schema.xsd"));


        XMLStreamReader2 xmlReader = (XMLStreamReader2) new WstxInputFactory().createXMLStreamReader(reader);
        xmlReader.validateAgainst(schema);

        XMLStreamWriter2 xmlWriter = (XMLStreamWriter2) new WstxOutputFactory().createXMLStreamWriter(writer);
        xmlWriter.validateAgainst(schema);

        xmlWriter.copyEventFromReader(xmlReader, false);

        while (xmlReader.hasNext()) {
            xmlReader.next();

            xmlWriter.copyEventFromReader(xmlReader, false);
        }

        System.out.println(writer.toString());
    }
}

这是 XML:

<?xml version="1.0" encoding="UTF-8"?>
<JobStatus xsdVersion="NA">
    <Document>
        <DocumentId>1234567890</DocumentId>
    </Document>
    <Document>
        <DocumentId>1234567891</DocumentId>
    </Document>
</JobStatus>

这是架构:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema elementFormDefault="qualified"
           xmlns:xs="http://www.w3.org/2001/XMLSchema">

    <xs:element name="JobStatus">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="Document" maxOccurs="unbounded">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="DocumentId" type="xs:string"/>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
            <xs:attribute name="xsdVersion" type="xs:string" use="required"/>
        </xs:complexType>
    </xs:element>
</xs:schema>

这一切都导致(启用了编写器的验证):

Exception in thread "main" com.ctc.wstx.exc.WstxValidationException: element "JobStatus" is missing "xsdVersion" attribute
        at [row,col {unknown-source}]: [1,66]
        at com.ctc.wstx.exc.WstxValidationException.create(WstxValidationException.java:50)
        at com.ctc.wstx.sw.BaseStreamWriter.reportProblem(BaseStreamWriter.java:1223)
        at com.ctc.wstx.msv.GenericMsvValidator.reportError(GenericMsvValidator.java:549)
        at com.ctc.wstx.msv.GenericMsvValidator.reportError(GenericMsvValidator.java:541)
        at com.ctc.wstx.msv.GenericMsvValidator.reportError(GenericMsvValidator.java:535)
        at com.ctc.wstx.msv.GenericMsvValidator.validateElementAndAttributes(GenericMsvValidator.java:343)
        at com.ctc.wstx.sw.BaseNsStreamWriter.closeStartElement(BaseNsStreamWriter.java:420)
        at com.ctc.wstx.sw.BaseStreamWriter.copyEventFromReader(BaseStreamWriter.java:807)
        at Converter.main(Converter.java:34)

无需对编写器进行验证,程序运行良好并返回作为输入提供的相同 XML(以一些缩进和换行差异为模)

所以我的问题是:我在 Woodstox 上做错了吗?为什么验证只在编写器上失败?

我可以使用其他 XSD 和 XML 对重现此问题,在这种情况下,您可能会遇到不同类型的错误,但总是在编写器方面。阅读器端的验证始终有效(只要 XML 明显符合 XSD)。

任何见解将不胜感激!

PS:供参考,这里是示例使用的依赖项和版本

  • org.codehaus.woodstox stax2-api 4.0.0
  • com.fasterxml.woodstox woodstox-core 5.0.2
  • net.java.dev.msv msv-core 2013.6.1
  • net.java.dev.msv xsdlib 2013.6.1

【问题讨论】:

  • 您是否尝试调用copyEventFromReader(xmlReader, true),即第二个参数使用true
  • 嗨@wero,是的,我试过了,你仍然得到同样的例外,将preserveEventData 设置为true,正如你所建议的那样。
  • 你可以调试并找出GenericMsvValidator.validateElementAndAttributes有问题的原因
  • MSV 库中发生的事情对我来说有点太神秘了,我尝试调试但我并没有真正获得比堆栈跟踪中的信息更多的信息,即出于某种原因它找不到 xsdVersion 属性。此外,正如我所提到的,这不是一个孤立的错误:使用不同的 XSD 和 XML,您会在文档的不同位置得到不同的错误。
  • 可能是bug,你可以提交报告

标签: java xml xsd stax woodstox


【解决方案1】:

这似乎是 Woodstox 在写入验证时的一个错误:https://github.com/FasterXML/woodstox/issues/16

该错误现已在 Woodstox 5.0.3 版中得到修复,但写入验证仍存在一些问题(请参阅 https://github.com/FasterXML/woodstox/issues/23)。

【讨论】:

    猜你喜欢
    • 2014-12-03
    • 1970-01-01
    • 1970-01-01
    • 2019-06-23
    • 1970-01-01
    • 1970-01-01
    • 2016-08-21
    • 2013-08-23
    • 2019-05-18
    相关资源
    最近更新 更多