Как часть приложения Java 6, я хочу найти все объявления пространства имен в документе XML, включая любые дубликаты.Найти все объявления пространства имен в документе XML - xPath 1.0 vs xPath 2.0
Редактировать: По желанию Мартина, вот код Java Я использую:
XPathFactory xPathFactory = XPathFactory.newInstance();
XPath xPath = xPathFactory.newXPath();
XPathExpression xPathExpression = xPathExpression = xPath.compile("//namespace::*");
NodeList nodeList = (NodeList) xPathExpression.evaluate(xmlDomDocument, XPathConstants.NODESET);
Предположим, что я это XML документ:
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:ele="element.com" xmlns:att="attribute.com" xmlns:txt="textnode.com">
<ele:one>a</ele:one>
<two att:c="d">e</two>
<three>txt:f</three>
</root>
Чтобы найти все объявления пространств имен, я применил этот xPath для XML-документа с использованием xPath 1.0:
//namespace::*
Он находит 4 объявления пространств имен, которые я ожидаю (и желание):
/root[1]/@xmlns:att - attribute.com
/root[1]/@xmlns:ele - element.com
/root[1]/@xmlns:txt - textnode.com
/root[1]/@xmlns:xml - http://www.w3.org/XML/1998/namespace
Но если я изменяю с помощью XPath 2.0, то я получаю 16 объявлений пространств имен (каждый из предыдущих деклараций 4 раз), что не то, что я ожидал (или желания):
/root[1]/@xmlns:xml - http://www.w3.org/XML/1998/namespace
/root[1]/@xmlns:att - attribute.com
/root[1]/@xmlns:ele - element.com
/root[1]/@xmlns:txt - textnode.com
/root[1]/@xmlns:xml - http://www.w3.org/XML/1998/namespace
/root[1]/@xmlns:att - attribute.com
/root[1]/@xmlns:ele - element.com
/root[1]/@xmlns:txt - textnode.com
/root[1]/@xmlns:xml - http://www.w3.org/XML/1998/namespace
/root[1]/@xmlns:att - attribute.com
/root[1]/@xmlns:ele - element.com
/root[1]/@xmlns:txt - textnode.com
/root[1]/@xmlns:xml - http://www.w3.org/XML/1998/namespace
/root[1]/@xmlns:att - attribute.com
/root[1]/@xmlns:ele - element.com
/root[1]/@xmlns:txt - textnode.com
Эта же разница заметна даже тогда, когда я использую не-сокращенный вариант заявления XPATH:
/descendant-or-self::node()/namespace::*
И это видно на различных анализаторах XML (LIBXML, MSXML.NET, Saxon), проверенных в oXygen. (Edit:. Как я уже потом в комментариях, это утверждение не верно, хотя я думал, что я был тестирования различных XML-парсеров, я на самом деле не было.)
Вопрос № 1: Почему разница от xPath 1.0 до xPath 2.0?
Вопрос №2: Возможно ли получение/получение желаемых результатов с использованием xPath 2.0?
Подсказка: Использование distinct-values()
функции в XPath 2.0 будет не вернуть желаемые результаты, так как я хочу все объявления пространства имен, даже если одно пространство имен дважды объявлено. Например, рассмотрим этот XML-документ:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<bar:one xmlns:bar="http://www.bar.com">alpha</bar:one>
<bar:two xmlns:bar="http://www.bar.com">bravo</bar:two>
</root>
Желаемый результат:
/root[1]/@xmlns:xml - http://www.w3.org/XML/1998/namespace
/root[1]/bar:one[1]/@xmlns:bar - http://www.bar.com
/root[1]/bar:two[1]/@xmlns:bar - http://www.bar.com
Джеймс, пожалуйста, покажите нам код нахождения пространства имен «заявления». В моем понимании XPath '// namespace :: *' находит все узлы пространства имен, которые отличаются от декларации пространства имен, поскольку узлы пространства имен существуют на каждый элемент узла и не разделяются между узлами. Таким образом, XML-документ с четырьмя узлами элементов, где есть три объявления пространства имен в корневом элементе, путь должен найти четыре узла пространства имен для каждого из четырех элементов. Насколько мне известно, это должно быть одинаковым между XPath 1.0 и 2.0. Также такая запись, как '/ root [1]/@ xmlns: txt', довольно вводит в заблуждение. –
Обозначение/root [1]/@ xmlns: txt происходит от oXygen. Это их представление узлов в нодлисте, что прекрасно. –
Java-код, добавленный выше. Довольно стандартный материал. Спасибо за объяснение. –