XML。 SAX。具有默认值的属性

时间:2013-02-28 15:18:57

标签: java xml-parsing sax

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

2 个答案:

答案 0 :(得分:3)

这就是属性的默认值应该如何工作。如果您需要区分这两种情况(默认值与明确指定但具有默认值),则必须从架构中删除默认值并将其应用于代码级别。

答案 1 :(得分:1)

将功能标记http://xml.org/sax/features/use-attributes2报告为true的SAX2解析器将为ContentHandler#startElement(String uri, String localName, String qName, Attributes atts)的{​​{3}}参数提供Attributes2接口的实例。该扩展接口提供了方法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);
    }
}