Неясные результаты с запросом jdom2 XPath
У меня проблема с jdom2 XPath:
test.xhtml код:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="cs" lang="cs">
<head>
<title>mypage</title>
</head>
<body>
<div class="in">
<a class="nextpage" href="url.html">
<img src="img/url.gif" alt="to url.html" />
</a>
</div>
</body>
</html>
Java-код:
Document document;
SAXBuilder saxBuilder = new SAXBuilder();
document = saxBuilder.build("test2.html");
XPathFactory xpfac = XPathFactory.instance();
XPathExpression<Element> xp = xpfac.compile("//a[@class = 'nextpage']", Filters.element());
for (Element att : xp.evaluate(document) ) {
System.out.println("We have target " + att.getAttributeValue("href"));
}
Но только с этим я не могу получить никакого элемента. Я обнаружил, что когда запрос //*[@class = 'nextpage']
, он находит это.
We have target url.html
Это должно быть что-то с пространством имен или что-то другое в заголовке, потому что без него он может генерировать какой-то вывод. Я не знаю, что я делаю не так.
1 ответ
Примечание: хотя это та же проблема, что и описанная в предложенном дубликате, этот другой вопрос относится к версиям 1.x JDOM. В JDOM 2.x есть ряд существенных отличий. Этот ответ относится к реализации XPath JDOM 2.x, которая существенно отличается.
Спецификация XPath очень ясно показывает, как пространства имен обрабатываются в выражениях XPath. К сожалению, для людей, знакомых с XML, обработка XPath для пространств имен немного отличается от их ожиданий. Это спецификация:
QName в тесте узла раскрывается в расширенное имя с использованием объявлений пространства имен из контекста выражения. Это происходит так же, как расширение для имен типов элементов в начальном и конечном тегах, за исключением того, что пространство имен по умолчанию, объявленное с помощью xmlns, не используется: если QName не имеет префикса, то URI пространства имен равен нулю (это то же самое способ расширения имен атрибутов). Ошибка, если у QName есть префикс, для которого нет никакого объявления пространства имен в контексте выражения.
На практике это означает, что всякий раз, когда у вас есть пространство имен "по умолчанию" в вашем XML-документе, вам все равно нужно добавлять префикс этого пространства имен при использовании его в выражении XPath. Метод XPathFactory.compile(...) ссылается на это требование в JavaDoc, но не так ясно, как должно быть. Используемый префикс произвольный и локальный только для этого выражения XPath. В вашем случае код будет выглядеть примерно так (при условии, что мы выбираем пространство имен xhtml
для URI http://www.w3.org/1999/xhtml
):
XPathFactory xpfac = XPathFactory.instance();
Namespace xhtml = Namespace.getNamespace("xhtml", "http://www.w3.org/1999/xhtml");
XPathExpression<Element> xp = xpfac.compile("//xhtml:a[@class = 'nextpage']", Filters.element(), null, xhtml);
for (Element att : xp.evaluate(document) ) {
System.out.println("We have target " + att.getAttributeValue("href"));
}
Я должен добавить это в FAQ... Спасибо.