0

我正在使用 java 8 的 DocumentBuilder 阅读 XML 文档,并尝试使用 jing 对 Relax NG Schema 进行验证。如果 XML 文档包含名称空间声明,这不起作用。

看下面的例子:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setValidating(false);
dbf.setNamespaceAware(true);

System.setProperty(SchemaFactory.class.getName() + ":" + XMLConstants.RELAXNG_NS_URI,
XMLSyntaxSchemaFactory.class.getName());

SchemaFactory rngSchemaFactory = SchemaFactory.newInstance(XMLConstants.RELAXNG_NS_URI);
rngSchemaFactory.setProperty("http://relaxng.org/properties/datatype-library-factory", new org.relaxng.datatype.helpers.DatatypeLibraryLoader());
InputStream is = getClass().getResourceAsStream("/path/to/schema.rng");
InputStreamReader rngReader = new InputStreamReader(is, "UTF-8");
Schema schema = rngSchemaFactory.newSchema(new StreamSource(rngReader));

dbf.setSchema(schema);

DocumentBuilder db = dbf.newDocumentBuilder();
db.setErrorHandler(new ErrorHandler());
Document doc = db.parse(Files.newInputStream(xmlFile, StandardOpenOption.READ));

这段代码解析 XML 文档,构建 DOM 并验证 XML 文档。但是,ErrorHandler 会收到以下三个错误消息:

Line 2, column 96, attribute "xmlns" not allowed here; expected attribute "id" or "unique-identifier"
Line 3, column 96, attribute "xmlns:dc" not allowed here; expected attribute "id"
Line 3, column 96, attribute "xmlns:opf" not allowed here; expected attribute "id"

xml 文档的前三行看起来像

<?xml version="1.0"?>
<package version="2.0" xmlns="http://www.idpf.org/2007/opf" unique-identifier="p9783701742455">
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">

XML 文档似乎完全有效。

当我在不构建 DOM 的情况下验证同一个文档时,不会遇到这些错误。看下面这段代码:

System.setProperty(SchemaFactory.class.getName() + ":" + XMLConstants.RELAXNG_NS_URI, XMLSyntaxSchemaFactory.class.getName());
SchemaFactory rngSchemaFactory = SchemaFactory.newInstance(XMLConstants.RELAXNG_NS_URI);
rngSchemaFactory.setProperty("http://relaxng.org/properties/datatype-library-factory", new org.relaxng.datatype.helpers.DatatypeLibraryLoader());

InputStream is = getClass().getResourceAsStream("/path/to/schema.rng");
InputStreamReader rngReader = new InputStreamReader(is, "UTF-8");
Schema schema = rngSchemaFactory.newSchema(new StreamSource(rngReader));

Validator validator = schema.newValidator();
validator.setErrorHandler(new ErrorHandler());
validator.validate(new StreamSource(xmlFile));

我掌握的最后一条信息是,SAX 解析器应该具有以下特性:

http://xml.org/sax/features/namespace-prefixes 当为真时,该特性表示 xmlns 和 xmlns:prefix 属性将包含在传递给 startElement( ) 的属性列表中。当为 false 时,这些属性将被省略。

我想,这似乎是我的问题的原因。但是,DocumentBuilderFactory 不支持此功能。

4

0 回答 0