我使用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中是否存在该属性吗?

最佳答案

将功能标记http://xml.org/sax/features/use-attributes2报告为true的SAX2解析器将为Attributes2Attributes参数提供ContentHandler#startElement(String uri, String localName, String qName, Attributes atts)接口的实例。此扩展接口提供了方法isSpecified(int index)isSpecified(String qName),其中的方法测试true如果在文档中指定了属性,或者测试了false如果该值是通过DTD或架构默认的。

我发现一个用例是在EPUB 3.0.1管道中将XHTML 4.01 Transitional转换为(X)HTML5。我遇到的一个障碍是,过渡DTD的<br>元素默认将属性clear设置为none;此属性在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);
    }
}

关于java - XML。萨克斯具有默认值的属性,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15139149/

10-11 22:23
查看更多