倭マン's BLOG

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

XPath を使う

今回は XPath を用いて、ノードを取得したり(属性などの)値を取得したりする方法を見ていきます(一覧)。

dom4jXPath 機能を利用するためには、XPath エンジンである Jaxen の jar ファイルをクラスパス内に含める必要があります*1

Node#selectNodes(String)


まず、XPath 式によってノードを取得する1番典型的なメソッド List Node#selectNodes(String) を見ていきましょう。 次節で紹介するその他の XPath を使うメソッドも、使い方は基本的に同じです。

以下のようなサンプルの XML データがあるとします。

<?xml version="1.0" encoding="UTF-8"?>

<locke publish-date="2007年9月18日">
    <comic title="超人ロック 完全版13" isbn="978-4-7859-2848-3" price="1200"/>
    <comic title="久遠の瞳3" isbn="978-4-8401-1947-4" price="580"/>
    <comic title="ひとりぼっちのプリンセス" isbn="978-4-8401-1948-1" price="580"/>
</locke>

以下の例では、上記のサンプルに対して、<comic> 要素のリストを取得して、各<comics> 要素の情報を表示しています(変数 doc は上記の XML データです):

for(final Object nodeObj: doc.selectNodes("/locke/comic")){
    final Element comic = (Element)nodeObj;

    System.out.println(
        "タイトル: "+comic.attributeValue("title")+"; "+
        "ISBN: "+comic.attributeValue("isbn")+"; "+
        "価格: "+comic.attributeValue("price"));
}

実行結果は

タイトル: 超人ロック 完全版13; ISBN: 978-4-7859-2848-3; 価格: 1200;
タイトル: 久遠の瞳3; ISBN: 978-4-8401-1947-4; 価格: 580;
タイトル: ひとりぼっちのプリンセス; ISBN: 978-4-8401-1948-1; 価格: 580;

となります。

Node#selectNodes() には、引数が String のもの以外に2つ、オーバーロードされたメソッドがありますが、ここでは省略します。

♪Node に定義されている XPath 関連メソッド♪


Node#selectNodes(String) 以外の XPath 関連のメソッドをまとめると、下表のようになります。

メソッド名 返り値 処理
selectSingleNode(String) Node XPath 式に合致するノードを1つ返します。
selectObject(String) Object XPath 式の評価結果を Object オブジェクトとして返します。
valueOf(String) String XPath 式の評価結果を文字列(String オブジェクト)として返します。
評価結果を文字列に変換するには XPath 仕様の string() 関数が用いられます。
numberValueOf(String) Number XPath 式の評価結果を数値(Number オブジェクト)として返します。
評価結果が数値でない場合は null を返します。

何点か注意を:

  • 各メソッドの引数の String は XPath 式です。
  • selectSingleNode()XPath 式に合致するノードが複数あった場合、JavaDoc には返されるノードは明記されていません。 デフォルト実装では、おそらく(document order で)最初に合致したノードが返されています。
  • JavaDoc によると、selectObject() の返り値は 「Node、Node のリスト、String、Number のいずれか」となっていますが、デフォルト実装では「Node、Node のリストのいずれか」のようです。

いくつか簡単なサンプルを挙げておきましょう。 doc で表される XML 文書は、前節で挙げたサンプルと同じものです:

// selectSingleNode() メソッド
Node title = doc.selectSingleNode( "/locke/comic/@title" );
System.out.println(title.getText());    
// 「超人ロック 完全版13」と出力
// (環境によっては実行結果が異なるかもしれません)

// valueOf() メソッド
String date = doc.valueOf( "/locke/@publish-date" );
System.out.println(date);    // 「2007年9月18日」と出力

// numberValueOf() メソッド
Number price1 = doc.numberValueOf( "/locke/comic[1]/@price" );
System.out.println(price1);    // 「1200」と出力

♪org.dom4j.XPath


org.dom4j.XPath は、XPath 式を表す Java インターフェースです。 1つの XPath 式を幾つかのノードに対して適用する際に用います。

使い方は以下の通り:

  1. XPath オブジェクトを生成する
  2. XPath オブジェクトのメソッドを用いて評価結果のノード(文字列、オブジェクト)を取得する

1. XPath オブジェクトを生成する

XPath オブジェクトをせいせいするには、Document や Element を生成したように org.dom4j.DocumentHelper を使用します:

XPath xpath = DocumentHelper.createXPath("/locke/comic");

2. XPath オブジェクトのメソッドを用いて評価結果を取得する

XPath に定義されているメソッドは、Node に定義されているものと同じ名前のものばかり(ただし、引数として Node オブジェクトを渡すところが異なる)なので、使用方法は分かると思います:

List comics = xpath.selectNodes(doc);
for(Object nodeObj: comics){
    Element comic = (Element)nodeObj;
    System.out.println(comic.attributeValue("title"));
}

*1:Maven2 で普通に Jaxen を依存性に含めると余計なライブラリがダウンロードされてしまいます。 これについてはそのうちに。