使用 Woodstox / Stax2 写入 XML 时验证失败

Validation fails when writing XML with Woodstox / Stax2

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

令人惊讶的是,验证问题仅在写入 XML(使用XMLStreamWriter2)时发生,而不会在读取[=49时发生=] XML(使用 XMLStreamReader2)。

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

现在,由于 编写器 的验证错误而失败。如果我停用对编写器的验证,一切都会顺利进行,并且编写器会完全符合 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)

未经作者验证,程序运行良好,returns 提供相同的 XML 作为输入(模数缩进和换行差异)

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

我可以用其他对 XSD 和 XML 重现这个问题,在这种情况下你会得到不同类型的错误,但总是在作者一方。 reader 方面的验证始终有效(只要 XML 显然符合 XSD)。

任何见解将不胜感激!

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

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

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

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