メメメモモ

プログラミング、筋トレ、ゲーム、etc

XPathメモ

ノード

ノードとは、HTML(XML)の情報をそのまま持っているオブジェクトです。
ノードには次のような種類があります。

  • 要素
    • タグを持ったノード
  • テキストノード
    • タグ内のテキスト部分
  • 属性
    • のclass="hoge"の部分

  • ドキュメント
    • 一番祖先の要素(htmlタグ)

XPath

次のようなものをXPath式と呼びます。

/descendant-or-self::node()/child::div


XPath式の項には次のような種類があります。

  • 数値の即値
  • 文字列の即値
  • 関数呼び出し
  • 丸カッコで囲まれたXPath
  • ロケーションパス


XPath式からノードを取得する行為を「XPath式を評価する」と表現します。
また、XPath式を評価して得られた結果を「評価値」と呼びます。
評価値の方には次のような型があります。

  • ノード集合型
  • 数値型
  • 文字列型
  • 真偽型

ロケーションパス

ロケーションパスとは、ノード集合を取得するための項です。
ロケーションパスの構成は次のようになります。

  • /
  • ロケーションステップ
  • /ロケーションステップ/ロケーションステップ・・・
  • ロケーションステップ/ロケーションステップ・・・
  • (評価値がノード集合になる項)/ロケーションステップ/ロケーションステップ・・・


ロケーションパスは、スラッシュとロケーションステップで構成されています。

ロケーションステップ

ロケーションステップは次の3要素で構成されています。

  • ノードテスト
  • 述語


記法としては次のようになります。

軸::ノードテスト[述語][述語]・・・


実際の記述は次のようになります。

child::div

軸とは、基準となるノードからどの方向をみるのかを決めるものです。
子ノードの方向をみるのか、
親ノードの方向をみるのか、などを決めます。


child::divは、「直接の子ノード」を見る指定になっています。

ノードテスト

ノードテストは、指定されたノードの名前または種類によって、ノード群からノードを選択します。
divという名前のノードを選択する、といった指定をします。


child::divは、divという名前のノードを選択する指定になっています。

述語

述語は、[]で囲まれたXPathです。
ロケーションステップの最後にくっつきます。
役割としては、ロケーションステップで得られたノード群の絞り込みを行ないます。
例えば、classがhogeで指定されているノード、といった指定を行ないます。


child::div[@class="hoge"]は、child::divで得られたノード群の中からclass="hoge"になっているノードを取得しています。

コンテキストノード

コンテキストノードは、基準となるノードです。
相対ロケーションパスが指定された時に、コンテキストノードが評価されます。
javascriptのevaluate関数の第二引数にはコンテキストノードを指定しますが、
「document」や「document.body」などを渡します。
第一引数のXPathに相対ロケーションパスが指定された場合、documentなどから評価されるようになります。

javascriptのdocument.evaluate関数

javascriptXPathを行なうには、次のような関数を使用します。

var result = document.evaluate(
   '//div',            // XPath
   document,     // コンテキストノード
   null,                // 基本nullで
   7,                    // 結果オブジェクトの形式、基本7でおk
   null);              // 基本nullで


基本的に使用する時は、XPath式とコンテキストノードの指定を気にすれば良いんじゃないかと思います。
下記の例は、divタグでclassがhogeのノードを取得しています。

<html>
  <head>
    <script type="text/javascript">
      window.onload = function() {
         var result = document.evaluate(
            '//div[@class="hoge"]',
            document.body,
            null,
            7,
            null);
         for (var i = 0; i < result.snapshotLength; i++) {
            alert(result.snapshotItem(i).innerHTML);
         }

     };
    </script>
    <title>Sample</title>
  </head>
  <body>
    <h1>fuga</h1>
    <div class="hoge">piyo</div>
    <div>pupu</div>
    <div class="hoge">popo</div>
  </body>
</html>

参考

WEB+DB PRESS Vol.42

WEB+DB PRESS Vol.42


JavaScriptで使うXPath入門「JavaScriptわくわく開発道第四回」