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
だから、私はどちらかを探しています:
- このクエリを機能させる方法、または
- プログラムで名前空間宣言を削除する方法、または
- これらの両方が間違っていると仮定して、正しいアプローチの説明。
更新: LevLevitskyの回答とJaxenFAQに基づいて、次のハックを思いつきました。
XPathContext context = new XPathContext(
"foo",
document.getRootElement().getNamespaceURI());
Nodes divs = document.query("//foo:div");
これはまだ少し気が狂っているように見えますが、Jaxenがあなたに何かをしてほしいと思っている方法だと思います。
アップデート#2:以下に記されているように、そしてインターネット全体で、これはJaxenのせいではありません。XPathがXPathであるだけです。
したがって、このハックは機能しますが、名前空間宣言を削除する方法が必要です。できればXSLTまでは行かないでください。