JavaScript: document.evaluateの第2引数に特定のノードを指定したときは頭に/を使ってはいけない

XPath で "//" を使う時は気をつけようという話 « のっち大好きの会 分室

第2引数を指定しても、頭に/をつけると無関係にルートノードが選択される。

document.evaluate('/', document.getElementById("menu"), null, 7, null).snapshotItem(0).nodeName
// -> "#document"
document.evaluate('//*', document.getElementById("menu"), null, 7, null).snapshotItem(0).nodeName
// -> "HTML"
document.evaluate('//*', document.getElementById("menu"), null, 7, null).snapshotLength
// -> 619

第2引数は単にドキュメント中の初期位置を指定するだけで、サブグラフを与えたりするわけではない

document.evaluate('../*', document.getElementById("menu"), null, 7, null).snapshotItem(0).nodeName
// -> "DIV"

とか普通にできる。


第2引数の指定を生かすには

  • 頭に.をつける
  • 頭に/をつけずに、decendant::ほかを使う

などする。

document.evaluate('self::*', document.getElementById("menu"), null, 7, null).snapshotItem(0).nodeName
// -> "DL"
document.evaluate('descendant::*', document.getElementById("menu"), null, 7, null).snapshotItem(0).nodeName
// -> "DT"
document.evaluate('.//*', document.getElementById("menu"), null, 7, null).snapshotLength
// -> 146

今まで何となく自作$X関数とかで

document.evaluate(xexp, root || document, null, 7, null);

とかやってたけど、この辺も注意が必要。

$X('//a', node)はダメで、$X('.//a', node)ならOKとか、そんな感じ。

というか、頭に/をつけること自体に警戒すべきか。

*、node()、text()、comment()

XML Path Language (XPath) # 2.3 ノードテスト

*
主ノード型のノードであればどのノードでも真
node()
どのような型のノードでも真
text()
どのテキストノードでも真
comment()
すべてのコメントノードで真

*のほうがnode()よりも限定的。*node()

document.evaluate('//*', document, null, 7, null).snapshotLength
// -> 655
document.evaluate('//node()', document, null, 7, null).snapshotLength
// -> 1521

探索対象をXHTML要素に限定できる場合は、node()よりも*を使ったほうが速そう。

Comment: 0

Comment Form
Name
URL
Comment

Trackback: 1

Trackback URL
http://mayokara.info/note/trackback/228
Attention
スパム対策のため、当エントリへのリンクがないトラックバックをブロックしています。
Google Reader のスターをまとめて開く Greasemonkey
sukechan.net 2008/09/13 21:47
これはなに? Google Reader でスターを付けた記事をまとめて開くことができる Greasemonkey です。 スター付きアイテムなどを開いた状態で、「o」キーを押すとスター付きの記事を最...