- < Newer
- Older >
フィードをオートディスカバリーする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とした場合などとの関係からこうなってるんでしょうね……
- < Newer
- Older >