当前位置: 首页 > 知识库问答 >
问题:

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

东郭鸿福
2023-03-14

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

令人惊讶的是,验证问题只发生在写入XML时(使用XMLStreamReader2),而不是读取XML时(使用XMLStreamReader2)。

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

现在,这将失败,写入程序将出现验证错误。如果我在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)

我可以用其他XSD和XML对再现这个问题,在这种情况下,您可能会得到不同类型的错误,但总是在writer端。读取器端的验证始终有效(只要XML明显符合XSD)。

任何见解将非常感谢!

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

    null

共有1个答案

郎曾笑
2023-03-14

write:https://github.com/fasterxml/Woodstox/issues/16验证时,这似乎是Woodstox中的一个bug

现在Woodstox的5.0.3版已经修复了这个错误,但是在写验证方面仍然存在一些问题(请参见https://github.com/fasterxml/Woodstox/issues/23)。

 类似资料:
  • 我一直在尝试改进针对XSD模式的XML验证性能,特别是关于XSD唯一约束的性能,并决定尝试一下Woodstox。我基本上遵循了这个示例,将更改为。 不过,我遇到的问题是,Woodstox验证器会发现XML有效,即使XML违反了唯一约束。将我的java代码切换回“常规”、和时,会正确检测到唯一性约束冲突。 此外,我可以确认Woodstox验证器做了一些事情,因为例如,如果我有一个负数,其中一个正数是

  • 问题内容: 显然在JAXB的版本2中-验证器类已被弃用- 这是否意味着编组器会自动验证您的XML?如果是这样,它似乎并没有抱怨我正在形成一些不正确的XML!谁能给我一些有关如何验证编组XML以确保其符合XSD架构的建议。 非常感谢。 问题答案: 通过使用JAXP 1.3 Schema Validation Framework,在JAXB 2.0中扩展了验证功能。 在哪里之前: 现在您需要执行以下操

  • 主要内容:形式良好的 XML 文档,验证 XML 文档,XML DTD,XML Schema,一个通用的 XML 验证器拥有正确语法的 XML 被称为"形式良好"的 XML。 通过 DTD 验证的XML是"合法"的 XML。 形式良好的 XML 文档 "形式良好"的 XML 文档拥有正确的语法。 在前面的章节描述的语法规则: XML 文档必须有一个根元素 XML元素都必须有一个关闭标签 XML 标签对大小写敏感 XML 元素必须被正确的嵌套 XML 属性值必须加引号 <?xml version=

  • 当我使用https:/rubygems时,我经常收到一个证书验证错误。组织。 提出了一种解决方法:删除“s”(因此我最终使用http而不是https)。它工作了一段时间,但今天在启动了一个新的rails应用程序之后,我得到了相同的证书验证错误: Gem::RemoteFetcher::FetchError:SSL\u connect返回=1 errno=0 state=SSLv3读取服务器证书B:

  • 现在,我正在用Spring MVC开发一个web应用程序。 样品值可以是“0.05”、“1.00”、“12.55”等。 因此,如果有任何办法来解决这个问题,请点亮我。谢了。