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