我在使用带有 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 做错了吗?为什么验证仅在 writer 上失败?
我可以使用其他 XSD 和 XML 对重现此问题,在这种情况下,您可能会遇到不同类型的错误,但总是在编写器方面。阅读器端的验证始终有效(只要 XML 明显符合 XSD)。
任何见解将不胜感激!
PS:供参考,这里是示例使用的依赖项和版本
- org.codehaus.woodstox stax2-api 4.0.0
- com.fasterxml.woodstox 伍德斯托克斯核心 5.0.2
- net.java.dev.msv msv-core 2013.6.1
- net.java.dev.msv xsdlib 2013.6.1<