JavaScript類総合
- 8 :l ★:2007/06/02(土) 03:48:07 ID:???
- XPath
http://www.infoteria.com/jp/contents/xml-data/REC-xpath-19991116-jpn.htm
仕様書があったので適当にJavaScriptのライブラリを作ってみた。
実行にはScrapBookのStd.jsが読み込まれている必要がある。パクリ元のprototype.jsとかいう奴でも動くかも知れないが。
XPath式を元に、与えられたノードに式を適用して結果を返す関数を生成する。
例えば、「XPath('count(//div[@class="Navi"])')」は、以下のような関数を返す。
function(c){
var ct=(c.constructor==XPath.Context)?c:(new XPath.Context(c));
return(ct["count"]((new XPath.NodeSet(ct.Node.ownerDocument)).Step("descendant-or-self").Step("child","div",0)));
}
[@class="Navi"]のような述語の中の式は、別の関数に分割され、XPath.ExprFuncsという配列に格納される。中の処理は以下のような感じ。
return(ct.eq((new XPath.NodeSet(ct.Node)).Step("attribute","class"),"Navi"));
XPath.ContextやXPath.NodeSetというクラスに、実際の処理を行うメソッドが定義されている。
count()のような関数や、「=」のような一部の演算子は、Contextのプロトタイプメソッドとして用意してある。
パスの処理では、「.Step("child","div",0)」という部分が「div[@class="Navi"]」に対応している。第3引数以降の数値は、述語の式に対応した関数のID。
なお、「and」のような一部の演算子は、そのまま「&&」のようなJavaScriptの演算子に変換される。
なにやら凄く冗長になっているような気がするが、割と仕様書の通りになっているはず。
しかし、未実装や適当な実装が多数。
まず、字句解析では、NCNameとかQNameというのがよく分からなかったので、正規表現が適当。
HTMLのタグ名には正しくマッチすると思うが。
構文解析は、構文解析器の書き方がよく分からなかったので適当。
演算子の優先順位とか結合規則が正しく働くのか怪しいが、そっくりそのままJavaScriptの式にしてしまうのだから大丈夫なはず。
「a<b<c」→「ct.lt(ct.lt(a,b),c)」のような変換は正しく行われているような気がする。
コア関数は、name、local-name、translateがよく分からないので未実装。まあ、HTMLでは使うまい。
その他、演算子や関数での型の変換とかがよく分からないので適当。
Step()では、preceding、following、namespace基準点が面倒くさいので未実装。何に使うんだか。
NodeSetは、重複チェックや並び順の処理を真面目にやっていないので、基準点によってはおかしくなるはず。
子孫要素を選択するだけなら大丈夫だと思うが。
その他、実行速度も全体的に駄目そうだ。
「//div」とかやると、ドキュメント内の全ての要素をチェックするので、もの凄く遅い。
コード生成の途中でgetElementsByTagName('div')にでも変換してやればましになるだろうか。
とりあえず、AutoPagerizeのページ(http://swdyh.infogami.com/autopagerize)に有ったXPathをいくつか試してみたところ、それなりに動作しているような気がする。
作ってみたものの、使い道は未定。
ScrapBook.user.jsでは、HTMLを作る際に必要な要素にはあらかじめidを振ってあるので、XPathで選択する必要はない。
AddScrap.jsでは、スクラップ対象のページの構造が分からないので、XPath式の作りようがない。
投稿ファイル名: XPath.zip
http://lukewarm.s151.xrea.com/b/file/1171809116_8.zip
サイズ: 5196 bytes
8KB
0ch BBS 2005-10-08