使用 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)。
我在使用 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)。