1

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"));
}

しかし、これだけでは何の要素も得られません。query が の場合//*[@class = 'nextpage']、それが見つかることがわかりました。

We have target url.html

それがなければ出力を生成する可能性があるため、ヘッダーに名前空間またはその他のものが含まれている必要があります。何が間違っているのかわかりません。

4

1 に答える 1

0

注: これは提案された複製で説明されている問題と同じですが、他の質問は JDOM バージョン 1.x に関連しています。JDOM 2.x には、多くの重要な違いがあります。この回答は、大幅に異なるJDOM 2.x XPath 実装に関連しています。

XPath 仕様は、XPath 式で名前空間がどのように扱われるかについて非常に明確です。残念ながら、XML に精通している人々にとって、名前空間の XPath 処理は予想とは少し異なります。これは仕様です:

ノード テストの QName は、式コンテキストからの名前空間宣言を使用して展開名に展開されます。これは、xmlns で宣言されたデフォルトの名前空間が使用されないことを除いて、開始タグと終了タグの要素タイプ名に対して展開が行われるのと同じ方法です: QName にプレフィックスがない場合、名前空間 URI は null です (これは同じです)。属性名が展開される方法)。QName にプレフィックスがあり、式のコンテキストに名前空間宣言がない場合はエラーです。

実際には、これが意味することは、XML ドキュメントに「デフォルト」の名前空間がある場合はいつでも、XPath 式で使用するときにその名前空間にプレフィックスを付ける必要があるということです。XPathFactory.compile(...) メソッドは JavaDocでこの要件をほのめかしていますが、本来あるべきほど明確ではありません。使用するプレフィックスは任意であり、その XPath 式に対してのみローカルです。あなたの場合、コードは次のようになります( xhtmlURIの名前空間を選択すると仮定します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 に追加する必要があります... ありがとうございます。

于 2013-12-21T13:45:23.147 に答える