XSD 1.1的xercesJ: Validator正确处理断言,SAXParser显然不能



我正在为我的java项目构建一个xml验证器xerces-2_11_0-xml-schema-1.1-beta库,以支持XSD 1.1特定的功能,如断言。

考虑这个模式

<?xml version="1.1" encoding="UTF-8"?>
<schema targetNamespace="http://www.example.org/Example" elementFormDefault="qualified" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.example.org/Example">
    <complexType name="NodeType">
        <sequence>
            <element name="Node" type="tns:NodeType"
                maxOccurs="unbounded" minOccurs="0">
            </element>
        </sequence>
        <attribute name="partnumber">
            <simpleType>
                <restriction base="string">
                    <pattern value="[A-Z0-9_-]+"></pattern>
                </restriction>
            </simpleType>
        </attribute>
        <assert test="starts-with(@partnumber,../@partnumber)"/>
    </complexType>
    <element name="Node" type="tns:NodeType"></element>
</schema>

我开始使用"javax.xml.validation"。验证器"类

...
StreamSource xmlSource = new StreamSource(new File("example.xml"));
SchemaFactory sf = SchemaFactory.newInstance("http://www.w3.org/XML/XMLSchema/v1.1");
Schema s = sf.newSchema(new File("example.xsd"));
Validator v = s.newValidator();
v.setErrorHandler(new MyErrorHandler())
v.validate(xmlSource)
...
private static class MyErrorHandler extends DefaultHandler {
...
        public void error(SAXParseException e) throws SAXException {
            System.out.println("Error: "); 
            System.out.println("   Public ID: "+e.getPublicId());
            System.out.println("   System ID: "+e.getSystemId());
            System.out.println("   Line number: "+e.getLineNumber());
            System.out.println("   Column number: "+e.getColumnNumber());
            System.out.println("   Message: "+e.getMessage());;
        }
...
}

此解决方案有效:示例中的断言测试。XSD被正确处理,XML文件的验证顺利运行(断言测试被正确评估)

然后我用sax解析器替换了Validator(原因:为了更好地控制sax解析阶段)

...
SchemaFactory sf = SchemaFactory.newInstance("http://www.w3.org/XML/XMLSchema/v1.1");
Schema s = sf.newSchema(new File("example.xsd"));
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setSchema(s);
spf.setNamespaceAware(true);
spf.setValidating(true);
spf.setFeature("http://apache.org/xml/features/validation/schema", true);
SAXParser parser = spf.newSAXParser();
XMLReader r = parser.getXMLReader();
r.setErrorHandler(new MyErrorHandler())
r.parse("example.xml");
...

在第二种情况下,解析阶段在xsd "assert"子句上遇到错误,消息如下:

s4s-elt-invalid-content.1: The content of 'NodeType' is invalid.  Element 'assert' is invalid, misplaced, or occurs too often.

如果我在示例中删除assert子句。xsd(从而使其与1.0兼容)验证可以正确运行,因此我认为SAXParser仍然可以使用1.0规范。

为了坚持1.1模式规则,我在配置SAXParserFactory或SAXParser本身时是否遗漏了一些东西?

我认为您的项目中缺少XPATH 2.0依赖项。请检查一下!

XML Schema 1.1 '断言'和'类型替代'需要XPath用于评估的2.0处理器。对于XSD 1.1断言,需要完整的XPath 2.0支持。对于XSD 1.1类型的替代品,XML模式引擎可以提供完整的XPath 2.0支持,或者可以实现一个更小的XPath 2.0子集,由XSD 1.1语言定义。

:http://xerces.apache.org/xerces2-j/faq-xs.html

最新更新