タグ「XPath」による検索結果 3

Search Form

フィードをオートディスカバリーするXPath、Firefox互換

フィードをオートディスカバリーする XPath - IT戦記


http://mxr.mozilla.org/mozilla/source/browser/base/content/pageinfo/feeds.js#39

http://mxr.mozilla.org/mozilla/source/browser/base/content/utilityOverlay.js#639

'/x:html/x:head/x:link[@href and (contains(concat(" ",translate(normalize-space(@rel),"DEF","def")," ")," feed ") or (contains(concat(" ",translate(normalize-space(@rel),"AELNRT","aelnrt")," ")," alternate ") and not(contains(concat(" ",translate(normalize-space(@rel),"EHLSTY","ehlsty")," ")," stylesheet ")) and (starts-with(normalize-space(@type),"application/rss+xml") or starts-with(normalize-space(@type),"application/atom+xml") or ((starts-with(normalize-space(@type),"text/xml") or starts-with(normalize-space(@type),"application/rdf+xml") or starts-with(normalize-space(@type),"application/xml")) and contains(concat(" ",translate(normalize-space(@title),"RS","rs")," ")," rss ")))))]'

x:というのはデフォルト名前空間を取るためのprefixなので、resolver使わないなら消してもOK。

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()よりも*を使ったほうが速そう。

XPathでposition()やlast()を使うときは要注意

nisefastforward.user.jsを更新(という名目の修正)しました。


で、覚え書き。

注: ロケーションパス //para[1] はロケーションパス /descendant::para[1] と 同じではない。 後者は、最初の para という名前の子孫エレメントを選択する。前者は、そのエレメントの親からみると最初の para という名前の子エレメントになる para という名前の子孫エレメントをすべて選択する。

XML Path Language (XPath) Version 1.0

//a[last()]/descendant::a[last()]では挙動が異なる。

ドキュメント内の最後のa要素を選択したいときは、後者のように書かなければならない。

前者は/descendant-or-self::node()/child::a[last()]の省略形なので、任意の親ノードからみた最後のa要素がすべて選択されることになってしまう。


別の例で言うと

//li[last()] = /descendant-or-self::node()/child::li[last()]
各リスト(ul・ol)の最後のli要素を集めたノード集合
/descendant::li[last()]
全li要素中の最後のノード

という感じ。


素人考えだと、//a/descendant::aの略としたほうがしっくり来るんだけど、これは//child::aとした場合などとの関係からこうなってるんでしょうね……