倭マン's BLOG

くだらない日々の日記書いてます。 たまにプログラミング関連の記事書いてます。 書いてます。

Jaxen 苦闘 (4) :XPath オブジェクトに名前空間コンテキストを設定する

今回は名前空間コンテキストの設定方法を見ていきます(記事一覧)。

どのようなときに名前空間コンテキストの設定をする?


名前空間コンテキストの設定方法を見る前に、どのようなときにそれを設定しなければならないのかを考えてみましょう。 基本的な使用目的は、「XPath 式を簡潔に書けるようにする」ことです。 まぁ、XML 文書で名前空間を接頭辞で指定するのと同じ目的です(当たり前か)。

★サンプル★

例えば、以下のような RELAX NG スキーマがあったとしましょう(RELAX NG を知っている必要はありません):

<rng:grammar xmlns:rng="http://relaxng.org/ns/structure/1.0">
  ...
  <rng:element>...</rng:element>
  ...
</rng:grammar>

この文書に対して、名前空間 "http://relaxng.org/ns/structure/1.0" に属する全ての <rng:element> 要素を取得する XPath 式を書きたいとしましょう。

名前空間が何も設定されていないとき、このような XPath 式は以下のようになります:

//*[namespace-uri() = 'http://relaxng.org/ns/structure/1.0'][local-name() = 'element']

明らかに書くのが面倒くさすぎる!

一方、接頭辞 "rng" に名前空間 URI "http://relaxng.org/ns/structure/1.0" が設定されている場合、XPath 式は

//rng:element

とすることが出来ます。

★注意点★

幾つか注意点を。

2つ目をもう少し詳しく説明しましょう。 次のような RELAX NG スキーマを考えます:

<grammar xmlns="http://relaxng.org/ns/structure/1.0">
  ...
  <element>...</element>
  ...
</grammar>

接頭辞を使っていないこと以外は上記のサンプルと同じです。 このとき、やはり名前空間 "http://relaxng.org/ns/structure/1.0" に属する全ての <element> 要素を取得したいとします。

まず、XPath

//element

は、名前空間コンテキストが設定されていても、いなくても、意図した <element> 要素を返しません。

一方、接頭辞 "rng" に名前空間 URI "http://relaxng.org/ns/structure/1.0" が設定されている場合、XPath

//rng:element

は、意図した <element> 要素を返します。

デフォルト名前空間を変更している場合(接頭辞なしの名前空間宣言がある場合)は、名前空間 URI の指定を忘れがちなので注意しましょう。

名前空間コンテキストの設定方法


XPath オブジェクトに名前空間コンテキストを設定する方法には、次の2つがあります:

  • NamespaceContext オブジェクトを作成・設定して、それを XPath オブジェクトにセットする
  • XPath オブジェクトに直接 (接頭辞, 名前空間 URI) の組をセットする

2つ目の方法は NamespaceContext クラスを直接扱う必要がないので簡単です。

★NamespaceContext オブジェクトを作成・設定して、それを XPath オブジェクトにセットする★

手順は以下の通り:

  1. NamespaceContext オブジェクトを取得する
  2. NamespaceContext に名前空間を登録する
  3. NamespaceContext を XPath にセットする

サンプルの Java コードを見た方が早いかな:

XPath xpath = ...  // XPath オブジェクトの取得

// 名前空間コンテキストの設定
// 1. NamespaceContext オブジェクトを取得する
SimpleNamespaceContext context = new SimpleNamespaceContext();

// 2. NamespaceContext に名前空間を登録する
context.addNamespace("pre", "http://www.foo.org/");
context.addNamespace("xlink", "http://www.w3.org/1999/xlink");

// 3. NamespaceContext を XPath にセットする
 xpath.setNamespaceContext(nsContext);

List result = xpath.selectNodes(..);  // 検索の実行

NamespaceContext インターフェースについては次回。

XPath オブジェクトに直接 (接頭辞, 名前空間 URI) の組をセットする★

この場合には、XPath#addNamespace() メソッドを用います。

XPath xpath = ...  // XPath オブジェクトの取得

// 名前空間を設定する
xpath.addNamespace("pre", "http://www.foo.org/");
xpath.addNamespace("xlink", "http://www.w3.org/1999/xlink");

List result = xpath.selectNodes(..);  // 検索を実行する