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

它必须是具有名称空间的东西或头中的任何其他东西,因为如果没有它,它可以生成一些输出。我不知道我做错了什么。

注意:尽管这与建议的副本中描述的问题相同,但其他问题与JDOM 1.x版本有关。在JDOM 2.x中存在许多显著差异。这个答案与JDOM 2.x XPath实现有关,后者有很大不同。

XPath规范非常清楚如何在XPath表达式中处理名称空间。不幸的是,对于熟悉XML的人来说,命名空间的XPath处理与他们的预期略有不同。这就是规格:

节点测试中的QName使用表达式上下文中的命名空间声明扩展为扩展名称。除了不使用用xmlns声明的默认名称空间外,这与对开始和结束标记中的元素类型名称进行扩展的方式相同:如果QName没有前缀,则名称空间URI为null(这与扩展属性名称的方式相同)。如果QName的前缀在表达式上下文中没有命名空间声明,则这是一个错误。

在实践中,这意味着,无论何时在XML文档中有一个"默认"命名空间,在XPath表达式中使用该命名空间时,都需要为其添加前缀。在JavaDoc中,XPathFactory.compile(…)方法暗示了这一要求,但它并不像应该的那样清晰。您使用的前缀是任意的,并且仅是XPath表达式的本地前缀。在您的情况下,代码看起来像(假设我们为URIhttp://www.w3.org/1999/xhtml选择名称空间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"));
}

我应该将此添加到常见问题解答中。。。谢谢

最新更新