1

我使用 SAX 处理 XML 文件:

XMLReader reader = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
reader.setFeature("http://xml.org/sax/features/validation", Boolean.TRUE);
reader.setFeature("http://apache.org/xml/features/validation/schema", Boolean.TRUE);

我加载语法(XSD)并将其设置给阅读器。

reader.setProperty("http://apache.org/xml/properties/internal/grammar-pool", grammarPool);

语法包含某些元素的某些可选属性的 defaultValue。那些具有默认值的属性会与此值一起从我的处理程序传递给 startElement(ContentHandler#startElement)) 方法,即使它们不存在于源 XML 中也是如此。我能否以某种方式验证该属性是否存在于 XML 中?

4

2 回答 2

3

这就是属性的默认值应该如何工作。如果您需要区分这两种情况(默认与显式指定但使用默认值),那么您必须从架构中删除默认值并改为在代码级别应用它。

于 2013-02-28T15:42:28.943 回答
1

报告功能标志的http://xml.org/sax/features/use-attributes2SAX2解析器true将为. 此扩展接口提供了方法和,这些方法测试是否在文档中指定了属性,或者该值是否通过 DTD 或模式默认。Attributes2AttributesContentHandler#startElement(String uri, String localName, String qName, Attributes atts)isSpecified(int index)isSpecified(String qName)truefalse

我发现的一个用例是在 EPUB 3.0.1 管道中从 XHTML 4.01 Transitional 转换为 (X)HTML5。我遇到的一个问题是过渡 DTD 的<br>元​​素默认属性clearnone; 此属性在 HTML5中无效。为了避免在 HTML5 中手动过滤所有无效属性,我Attributes通过过滤默认属性来重建一个,如下所示:

public static Attributes filterDefaults(Attributes attributes) {
    // Either test the feature flag, or do an instance test
    Attributes2 attrs = (Attributes2) attributes;
    Attributes2Impl newAttrs = new Attributes2Impl();
    for (int i = 0; i < attrs.getLength(); i++) {
        if (attrs.isSpecified(i)) {
            final String qName = attrs.getQName(i);
            final String type = attrs.getType(i);
            final String value = attrs.getValue(i);
            newAttrs.addAttribute(null, null, qName, type, value);
        }
    }
    return newAttrs;
}

应该设置为XMLReader验证 DTD 或模式以及输入 XML,或多或少如下:

/**
 * @see "https://xerces.apache.org/xerces2-j/features.html"
 */
private XMLReader buildParser(SAXParserFactory parserFactory) throws SAXException {
    try {
        final SAXParser parser = parserFactory.newSAXParser();
        final XMLReader reader = parser.getXMLReader();
        if (!reader.getFeature("http://xml.org/sax/features/use-attributes2"))
            throw new SAXException("SAX2 parser with Attributes2 required");

        // Set your callback instances here
        reader.setEntityResolver(/*...*/);
        reader.setErrorHandler(/*...*/);
        reader.setContentHandler(/*...*/);
        reader.setProperty("http://xml.org/sax/properties/lexical-handler", /*...*/);

        reader.setFeature("http://xml.org/sax/features/namespaces", true);
        reader.setFeature("http://xml.org/sax/features/validation", true);
        reader.setFeature("http://apache.org/xml/features/validation/schema", true);

        return reader;
    } catch (ParserConfigurationException e) {
        throw new SAXException("Can't build parser", e);
    }
}
于 2018-08-02T21:36:03.577 回答