パスワードを忘れた? アカウント作成
504360 journal

airheadの日記: memo: Xpath学習帳 7

日記 by airhead

Xpath学習帳。コメントに続く。

(01/28 21:00 追記)Xpath検証用テストページ (MD5: 234a9e3b277ae9aa31eb408867254191)

この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
  • HTML文書に対して //div[@class='blue'] というXpath式を用いると、文書内にある「class属性の値がblueであるdiv要素すべて」がノード集合として返される。ここで、 //div[@class='blue'][3] という式で「それらdiv要素のうち3番目のもの」が返されるものと思ったが、これは間違いだった。 //div[@class='blue'] および //div[3] の、2つの集合の積集合が返されるだけだった。

    Opera 9.10では //[name()='div'][@class='blue'][3] という式で「class属性の値がblueであるdiv要素のうち、3番目のもの」が返されることがわかったが、Firefox 2.0では「正当な式にあらず」例外になる。どうしたものか。

    • しかし親コメント第3段落にあるような、ノードテスト部の無い(?)式というのもも正しくないように思える。テストページでいろいろ試してみたところ、次の2番目の式で目的のものが得られるとわかった。

      //div[@class='blue'][3]
      コンテキストノード以下に div[@class='blue'] を探す。マッチしたdiv要素が、それ自身とそのsiblingのうちで3番目に登場する div[@class='blue'] であれば、集合に加える。複数マッチする可能性がある。
      /descendant-or-self::div[@class="blue"][3]
      コンテキストノード以下に div[@class='blue'] を探す。マッチしたdiv要素が、コンテキストノード以下に3番目に登場する div[@class='blue'] であれば、集合に加える(単一要素の集合を返す)。複数マッチしない。
      親コメント
      • 考えてみれば // /descendant-or-self::node()/ の短縮形だ。最初に試した式は次の1行目と等価だから、
        /descendant-or-self::node()        /div[@class="blue"][3]
        /コンテキストノード以下の任意ノード/div[divの述部]

        /descendant-or-self::div               [@class="blue"][3]
        /コンテキストノード以下のdiv           [divの述部]

        コンテキストノード以下のすべてのノードのについて、述部条件を満たすdivが検索される、ということか。

        親コメント
        • というあたりの話は、仕様書 短縮シンタックス [w3.org](翻訳1 [doraneko.org]、翻訳2 [infoteria.com])の注記にも書いてあったか。きちんと読まねば。

          親コメント
        • もう一つ訂正。式が / で始まっている時点でドキュメントルートを指す。親コメントの式はコンテキストノードとは関係なく、次のような意味となる。

          /descendant-or-self::node()        /div[@class="blue"][3]
          ドキュメントルート以下の任意ノード /div[divの述部]

          /descendant-or-self::div               [@class="blue"][3]
          ドキュメントルート以下のdiv            [divの述部]

          これはテストページでも確認できる。コンテキストノードを文書中のdiv要素に取っていても、 //title //script でテストページのtitle要素やscript要素が得られる。

          コンテキストノード以下に3番目に登場する div[@class='blue'] を求めるような場合には ./descendant-or-self::div[@class='blue'] としなくてはいけない。コンテキストノードの子孫にdiv要素をすべて検索するような場合には、単純に .//div でよいだろう。

          なんだか、スタート地点の数文字で七転八倒してるな。

          親コメント
  • 次の4つの型で、返される集合にノードの順序の変動はあるか。ブラウザによって違いはあるか。元からあったノードとスクリプトで追加されたノードで、違いはあるか。調べてみた。

    • ORDERED_NODE_ITERATOR_TYPE
    • UNORDERED_NODE_ITERATOR_TYPE
    • ORDERED_NODE_SNAPSHOT_TYPE
    • UNORDERED_NODE_SNAPSHOT_TYPE

    Firefox 2.0では、返される集合のノードの順序は、すべての型でDOMツリーでの位置順になった。

    Opera 9.10では式に依存する。ORDERED_NODE_SNAPSHOT_TYPEでは常にDOMツリー順となる。それ以外の3つの型では、式が複数の式の和からなる場合に(例: //div[@class='blue'] | //div[1] | //div[3] )、最初の式( //div[@class='blue'] )のDOMツリー順集合、次の式( //div[1] )のDOMツリー順集合(除く重複)、次の式( //div[3] )のDOMツリー順集合(除く重複)...という集合が返される。

    文書に元々書かれているノード、DOMメソッドで追加したノード、innerHTMLで追加したノード、これらの違いは順序に影響しない。

    Xpathがまだよくわかっていないため、単純な調査のみしかできていない。他にも順序に影響する要因があるかもしれない。

    • テストページの誤りにより、検証結果にも誤りがあった。その訂正。

      Firefox 2.0ではすべての型でDOMツリー位置順、これは親コメントの通り。

      Opera 9.10で式が複数の式の和からなる場合、ORDERED型2つではDOMツリー位置順となる。同条件でUNORDERED型2つでは、個々の式の集合(DOMツリー位置順)を式の順に並べた集合が返される。

      親コメント
typodupeerror

身近な人の偉大さは半減する -- あるアレゲ人

読み込み中...