2

XOMを使用して外部システムから返されたHTMLを解析しようとしています。HTMLは次のようになります。

<!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="en" lang="en">
<body>
  <div>
    Help I am trapped in a fortune cookie factory
  </div>
</body>
</html>

(実際にはかなり厄介ですが、このDOCTYPE宣言と、これらの名前空間および言語宣言があり、上記のHTMLは実際のHTMLと同じ問題を示します。)

私がやりたいのは、のコンテンツを抽出することです<div>が、名前空間宣言はXPathを混乱させるようです。名前空間宣言を(手動で、ファイルから)削除すると、次のコード<div>で問題が見つかりません。

Document document = ...
Nodes divs = document.query("//div");

ただし、名前空間を使用すると、返さNodesれるサイズは0になります。

プログラムで名前空間を削除した場合はどうでしょうか。

Element rootElement = document.getRootElement();
rootElement.removeNamespaceDeclaration(rootElement.getNamespacePrefix());

...動作するはずですが、何もしません。javadocから:

このメソッドは、で追加された追加の名前空間のみを削除しますaddNamespaceDeclaration.

さて、私はクエリに名前空間を提供すると思いました:

XPathContext context = 
    XPathContext.makeNamespaceContext(document.getRootElement());
Nodes divs = document.query("//div", context);

サイズはまだゼロです。

名前空間コンテキストを手動で構築するのはどうですか?

XPathContext context = context = new XPathContext(
     rootElement.getNamespacePrefix(), rootElement.getNamespaceURI());
Nodes divs = document.query("//div", context);

コンストラクターは次のXPathContextように爆発します。

nu.xom.NamespaceConflictException: 
    XPath expressions do not use the default namespace

だから、私はどちらかを探しています:

  1. このクエリを機能させる方法、または
  2. プログラムで名前空間宣言を削除する方法、または
  3. これらの両方が間違っていると仮定して、正しいアプローチの説明。

更新: LevLevitskyの回答JaxenFAQに基づいて、次のハックを思いつきました。

XPathContext context = new XPathContext(
    "foo", 
    document.getRootElement().getNamespaceURI());
Nodes divs = document.query("//foo:div");

これはまだ少し気が狂っているように見えますが、Jaxenがあなたに何かをしてほしいと思っている方法だと思います。


アップデート#2:以下に記されているように、そしてインターネット全体で、これはJaxenのせいではありません。XPathがXPathであるだけです。

したがって、このハックは機能しますが、名前空間宣言を削除する方法が必要です。できればXSLTまでは行かないでください。

4

2 に答える 2

2

あなたは書ける:

Nodes divs = document.query("//*[local-name()='div' and namespace-uri()='http://www.w3.org/1999/xhtml']");
于 2013-04-02T23:17:30.547 に答える
1

名前空間を次のように直接指定する必要があります

Nodes divs = document.query("//{http://www.w3.org/1999/xhtml}div");

または、それぞれの名前空間にマップされているプレフィックスを使用します(これNamespaceContextが目的だと思いますが、クエリにプレフィックスはありません)。

残念ながら、Javaでどのように実装されているかはわかりませんが、役立つ場合はPythonの例を提供できます。

于 2012-03-12T20:16:22.363 に答える