使用relax ng和名称空间验证xml文档

时间:2017-11-08 17:24:52

标签: java dom namespaces relaxng jing

我正在使用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     如果为true,则此功能表示xmlns和xmlns:prefix属性将包含在传递给startElement()的属性列表中。如果为false,则省略这些属性。

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

0 个答案:

没有答案