Почему нет синтаксиса XPath для узлов с ограниченным пространством имен?
Некоторые узлы в документе XML имеют пространства имен, заданные с определенным префиксом.
В XPath 1.0 можно указать local-name() и игнорировать пространства имен.
Тем не менее, я хочу, чтобы сценарист XPath обнаружил узлы, используя их полное имя, имя которого было присвоено именам имен, в качестве идентификатора.
Рекомендуемым способом является добавление объявлений пространства имен в вызывающий код (в моем случае, Java). Но это означает, что человек, пишущий Xpath, не имеет возможности работать с пространствами имен!
Как найти узлы по их полным именам с использованием чистого XPath?
Ответы
Ответ 1
Не уверен, что вы имели в виду под "как идентификатор".
Как найти узлы по их полным именам с использованием чистого XPath?
В XPath 1.0, используя local-name() и namespace-uri(), например
"*[local-name() = 'foo' and namespace-uri() = 'http://my.org/ns/2.0']"
В XPath 2.0 существует более богатый набор функций, связанных с пространствами имен, например. namespace-uri-from-QName()
. Но я не уверен, что они улучшат выше, что вы хотите.
Ответ 2
XPath 3.0, который в настоящее время находится в рабочем статусе проекта, будет содержать буквальное выражение для URI с квалификацией QNames, позволяющее напрямую указывать пространство имен uri.
Вот несколько примеров EQNames:
- pi - это лексическое QName без префикса пространства имен.
- math: pi - лексическое QName с префиксом пространства имен.
- "http://www.w3.org/2005/xpath-functions/math": pi указывает URI пространства имен с использованием URILiteral; это не лексическое QName.
Я думаю, Saxon 9.3 включает в себя реализацию реализации xpath 3.0, которая должна использоваться с помощью java api.
Ответ 3
Вы можете использовать пространства имен во время запросов XPath. В Java вам нужно предоставить реализацию NamespaceContext, если вы также хотите использовать префиксы в этих запросах вместо полного пространства имен все время. Просто добавьте экземпляр NamespaceContext
к вашему XPath
- я предполагаю, что вы используете стандартную реализацию JDK, - но эта концепция применима и к Jaxen или другим пользователям.
Затем вы можете выполнять такие запросы, как //customns:Element
.
Если вы не используете или не можете использовать NamespaceContext
(по какой-либо причине), единственное решение, похоже, использует функции local-name
и namespace-uri
:
Document doc = ...;
XPath xp = XPathFactory.newInstance().newXPath();
String name = "Element";
String ns = "http://www.custom.org/#";
String expr = "//*[local-name() = '"+name+" and namespace-uri() = '"+ns+"']";
Node node = ((NodeList)xp.evaluate(expr, doc, XPathConstants.NODESET)).item(0);
Ответ 4
В спецификации для XPath 3.0 говорится:
Q{http://www.w3.org/2005/xpath-functions/math}pi
Это работает в этот момент (октябрь 2015 г.), например, в eXist-db.