Hatena::Groupos0x

FFFF RSSフィード

0xFFのメモです。

2008 June 20th Friday

あるテキストを含むコメントノードを取得するXPath

| 03:40 | あるテキストを含むコメントノードを取得するXPath - FFFF を含むブックマーク はてなブックマーク - あるテキストを含むコメントノードを取得するXPath - FFFF

経緯*1は省いて、結論

//node()[local-name()="" and not(self::text()) and contains(string(self::node()),"comments") ]

また酷く実装に依存しそうだけど、Firefox2/3とOpera9.50では動くのを確認。

もっとスマートな方法があるのかな?

nanto_viさんに

//comment()[contains(., "foo")]

でいけると教えていただきました。

あわせて読みたい


以下、もはや蛇足


で、折角なので少し解説を。

仕様書におけるコメントノード

展開された名前を持たない

とされています。

なので、local-name()=""と。

また、当然テキストノードではないので、not(self::text())

さらに、

コメントの文字列値はコメントのコンテンツである

ので、自身をstring()でキャストしたものをcontainsで調べれば特定の文字列を含むコメントノードにマッチします。

このとき、containsを使うならstring()は省略できますが、わかりやすいので残してあります。


コメントノードを手軽に取得できるならヒアドキュメント利用という手もありますね。

*1:イマイチそうなSITEINFOを見つけて、ちょっと直してみるかと思ったらもの凄いtable入れ子でどうしようもない感じで仕方ないかーと思いつつ、コメント部分にマッチさせれば少し綺麗になるかも?と思ったけど、コメントノードのマッチの仕方がわからないぞということで、チャレンジしてみた。

javascripterjavascripter2008/06/21 14:26Firebugの$xで試したところ、空の配列が返ってきました。
DOM構築時にコメントノードが削除されているようなんですが、どういう場合にこのXPathが使えるんでしょうか。

os0xos0x2008/06/21 14:41Firebugの$xは要素ノードしか返してくれないんですよね。。
cho45さんの$Xとか、普通にdocument.evaluate使えば取得できます。

Firebugの$xを何とかする場合は http://labs.gmo.jp/blog/ku/2008/05/firebug12alphaxuserchromejs.html をどうぞ。

nanto_vinanto_vi2008/06/21 15:26ノードテストでコメントノードを選別できるのでそれを使えばいいんじゃないでしょうか。
//comment()[contains(., "foo")]
Firefox 3、Safari 3.0.4 Beta、Opera 9.27/9.50では大丈夫そうでした。

os0xos0x2008/06/21 15:49nanto_viさん、ありがとうございます。追記させていただきました。

javascripterjavascripter2008/06/21 16:35(Firebug1.20b3デフォルトの)$xを使ってコメントノードを抽出できました。また、html、xhtmlのどちらも<script><!-- コード --></script>となっている部分のコメントノードは取得できませんでした。
Firebugの問題じゃなくて、単に互換性の確保のために一部がコメントとして解釈されなかっただけみたいです。お騒がせしました。

nanto_vinanto_vi2008/06/21 19:19> javascripterさん
HTMLの仕様上、script要素内の<!--はコメントの開始とは解釈されないのでコメントノードも存在しませんが、XHTMLならコメントの開始と解釈されコメントノードが生成されるはずです。
実際Firefox 3、Safari 3.0.4 Beta、Opera 9.27/9.50でXHTMLのscript要素内のコメントノードを取得できました。
XHTMLをtext/htmlで読み込んでいませんか? 多くのブラウザではapplication/xhtml+xml、applicatoin/xml、text/xmlで読み込まないとXHTMLとして扱ってくれません。

javascripterjavascripter2008/06/21 20:56>nanto_viさん
text/htmlとして読み込むとXHTMLとして扱われないんですね。知りませんでした。
仕様書もきちんとあたってみようと思います。

2008 April 8th Tuesday

jottit.comのLDRize用XPath

| 13:00 | jottit.comのLDRize用XPath - FFFF を含むブックマーク はてなブックマーク - jottit.comのLDRize用XPath - FFFF

jottit.com を ldrize 化した!!! - twwpの件。

元のXPathで動作は問題ないけど、折角なので少し簡潔にしつつパフォーマンスもアップさせてみた。

//http://constellation.jottit.com/siteinfoで実行
var s;
console.time('ori');
for (var i = 0;i<1000;i++){
    s = $x('id("content")//h1 | id("content")//h2 | id("content")//h3 | id("content")//h4 | id("content")//h5 | id("content")//h6');
}
console.timeEnd('ori');//ori: 4391ms
console.time('my');
for (var i = 0;i<1000;i++){
    s = $x('id("content")/descendant::*[self::h1 or self::h2 or self::h3 or self::h4 or self::h5 or self::h6]');
}
console.timeEnd('my');//my: 1437ms

2つ目のほうが高速な理由は、「100を取得して2に絞り込む処理」を10回やるより、「100を取得して20に絞り込む処理」を1回だけ行ったほうが効率的だから。

場合によるけど、|は非効率になりがちなので注意。

taizoootaizooo2008/04/08 13:11os0xセンセー descendant::*[self::h1 or self::h2]ってはじめてみましたー。まだまだ修行が足りないです。がんばります。

2008 March 7th Friday

ここよりも後でここより前を指定するXPath

| 00:21 | ここよりも後でここより前を指定するXPath - FFFF を含むブックマーク はてなブックマーク - ここよりも後でここより前を指定するXPath - FFFF

AutoPagerize pageElement ここよりもあとでここより前、みたいなのが書きたいとき - ロックスターになりたいより

following-sibling::node()[ ./following-sibling::*/descendant-or-self::kokomade ]

なるほどー。これ前やろうとして挫折したんだよなぁ。

少し改良(悪かも?)してみる

following-sibling::node()[ following::kokomade ]

[]ない先頭の./はなくてokっぽい。following-sibling::*/descendant-or-self::は、followingとほぼ同じなはず(厳密には違うけど、動作上は問題ないっぽい)。


ついでに@ITの改案。

### @IT
<textarea class="autopagerize_data" readonly="readonly">
url:          http://www.atmarkit.co.jp/
nextLink:     img[contains(@src,"/next.gif")]/parent::a
pageElement:  id("headmenu")/following-sibling::*[ following::img[contains(@src,"/next.gif")] ]
exapmleUrl:   http://www.atmarkit.co.jp/fsecurity/special/107bayes/bayes02.html
</textarea>
<textarea class="autopagerize_data" readonly="readonly">
url:          http://www.atmarkit.co.jp/
nextLink:     id("centercol")/p/b/a[contains(text(),"次のページ")]
pageElement:  //h2[@class="subhead1"]/following-sibling::*[following::p[@class="nextprev"]]
exapmleUrl:   http://www.atmarkit.co.jp/im/ces/serial/marketing/01/01.html
</textarea>

node()テキストノードなどを含むが、*は含まない。@ITの場合、*で足りるっぽい。


書き方のコツはinfogamiだとアカウント取れないので、避難所のほうが嬉しいかも。