Проверьте документ XML с помощью релакс-нг и пространств имен
Я читаю XML-документ с DocumentBuilder из Java 8 и пытаюсь проверить его с помощью Jing против схемы Relax NG. Это не работает, если 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: будут включены в список атрибутов, передаваемый startElement(). Когда false, эти атрибуты опущены.
Я думаю, что это, кажется, причина моей проблемы. Однако DocumentBuilderFactory не поддерживает эту функцию.