Version 26 (modified by amachang, 4 years ago)

--

XPath から CSS Selector への変換を真剣に検討するページ

XPath を IE8 で querySelector 出来るセレクタに変換する方法を考えよう」

HTML で使用することに特化していい

XPath から要素を取得する過程で使う目的

ブレスト

出来る系

//aaa//bbb//ccc
=> aaa bbb ccc

/aaa/bbb/ccc
=> html > bbb > ccc (ルートは html と決まっているから妥協)

id("hoge")
=> #hoge

id("hoge") | //aaa[@hoge="fuga"]
=> #hoge, aaa[hoge="fuga"]

//aaa/*[1]
=> aaa > *:first-child

//aaa[contains(@hoge, 'fuga')]
=> aaa[hoge*="fuga"]

//aaa[ends-with(@hoge, 'fuga')]
=> aaa[hoge$="fuga"]

(//aaa | //bbb)/ccc
=> aaa > ccc, bbb > ccc

//aaa[@hoge=1+1]
=> aaa[hoge="2"]   (パース時に定数を計算しているので)

出来ない系

aaa/bbb/ccc
=> child 軸から始まる (一時的に id を付けてやるのはどうか、パフォーマンス気になる)

./aaa/bbb/ccc
=> self 軸

..
=> parent 系の軸や兄要素にさかのぼる系

//aaa[.="hoge"]
=> 条件部に属性以外の条件

//aaa[@hoge=count(.//bbb//ccc)]
=> ネストしている (パース時に .//bbb//ccc をセレクタに直して実行し、 .//bbb//ccc の値が確定したら全体をセレクタに直して実行するのはどうか)

IE8 で対応するセレクタ

http://msdn.microsoft.com/en-us/library/cc351024%28VS.85%29.aspx

  • Simple Selector
    • .value
    • #value
    • E
    • *
    • [att=val]
    • [att]
    • [att|=val]
    • [att~=val]
    • [att^=val]
    • [att*=val]
    • [att$=val]
  • Combinator
    • E + F
    • E > F
    • E F
    • E ~ F

方法を考える

走り書きで

方法 1

  1. XPath をパースする
    1. 定数に出来るところはする
  2. 構文木を変換できる部分木を探す
    1. 上から順に走査 (ループ a)
      1. UnionExpr? があった場合
        1. UnionExpr? で繋がれた一連の PathExpr? のリストを走査する (ループ b)
          1. 以下のような PathExpr? がある場合はループ b を終了
            1. context-node() (JavaScript?-XPath 独自の概念) から始まる。ただし、以下の場合を除く
              1. context-node() の次の Step が child 軸で
              2. NodeTest?NameTest?
              3. NameTest? が html, head, body のいずれかである場合
      2. PathExpr? があった場合
  3. ---------------------------
    1. 上から順に変換する
      1. Step は以下の様に変換する
        1. (FIXME) Predicate も含め、すべて変換できる Step は
        2. (FIXME) 属性軸以外の軸で始まる LocationPath? がオペランドとして現れた場合、それを含む式は変換できない
      2. id 関数は以下の様に変換する
      3. UnionExpr? は以下のように変換する
  4. 実行する