jQuery をSQLの「select文」のように使う方法
jQueryオブジェクトを,まるでSQLのselect文のような呼び出し方で使える関数を作成した。
面白いだろうと思ってやっつけで作ってみたのだが,下記のようなコードが書ける。
jselect( "select * from document where id = p1" ).each(function(){ alert( $(this).text() ); });
こうすると,documentから全てのタグをスキャンし,id が "p1" であるようなDOM要素をjQueryオブジェクトとして返却し,そのタグ中のテキストを表示する。
要するに, $( "#p1" ) に変換している。
jselect( "select p from div" )
これは,div要素(親要素)の中にあるp要素をすべて返却する。つまり $( "div p" ) のこと。
正規表現によるセレクションもできる。
jselect( "select p from document where id ^= p and class $= hoge" )
とすれば,IDが "p" で始まり, CSSのclassが "hoge" で終わるような p 要素を document からすべて拾い出す。
生のjQueryで書けば, $( "p[@id^='p'][@class$='hoge']" ) という事だ。
*= によるマッチや, .classname による指定もできる。
要するに,
- HTMLのDOM構造に対してSQL文のようなものを発行すると,
- それを解釈してjQueryの記法に変換する
というだけで,実際のセレクション処理には関わってはいない。
このjselectという関数のコードを下記に記す。
// <script src="jquery-1.2.6.min.js"></script> // jQueryオブジェクトをSQLのselect文のように呼び出す function jselect( sql ){ // 解釈 var sql_info = getSqlInfo( sql ); // セレクタ文構築 var str_selector = getStrSelector( sql_info ); // jQueryオブジェクトを返す return $( str_selector ); // --- 以下関数 --- // SQL文を受け取り,属性情報をオブジェクトで返す function getSqlInfo( str ) { str = str .replace( /(select.+)/gi, "$1" ) .replace( " ", " " ); var part = str.split( " where " ); // 結果情報をセットするオブジェクト var ret_obj = {}; // 前半 (タグ名,親要素を指定) part[0].match( "select (.+) from (.+)" ); ret_obj.tags = {eq:"=", val:RegExp.$1}; ret_obj.from = {eq:"=", val:RegExp.$2}; // 後半 (id, class, name等を指定) if( part.length > 1 ) { $.each( part[1].split( / and /i ), function(i){ this.match( /(.+) (.?=) (.+)/ ); var key = RegExp.$1; var t_eq = RegExp.$2; var t_val = RegExp.$3; ret_obj[ key ] = {eq:t_eq, val:t_val}; }); } return ret_obj; } // 属性情報を受け取り,セレクタ文を返す function getStrSelector( obj ) { // 抽出 var tags = "" + obj.tags.val.replace("*",""); var from = "" + obj.from.val.replace("document",""); var id = ("id" in obj && obj.id.eq == "=") ? obj.id.val : null; var class = ("class" in obj && obj.class.eq == "=") ? obj.class.val : null; // セレクタ文の構築を開始 var ret = ""; ret += (from.length > 0) ? from + " " : ""; ret += (tags.length > 0) ? tags : ""; ret += (class) ? "." + class : ""; ret += (id) ? "#" + id : ""; // その他の属性 for( attr in obj ) { if( ("id" in obj && (!id) && attr === "id") || ("class" in obj && (!class) && attr === "class") || ( attr !== "id" && attr !== "class" && attr !== "from" && attr !== "tags" ) ) { ret += "[@" + attr // 属性名 + obj[attr]["eq"] // 符号 + "'" + obj[attr]["val"] // 値 + "']"; } } //alert(ret); return ret; } }
返ってきたオブジェクトに
.each(function(){ alert( this.innerHTML ); });
とか付加すれば,それらのオブジェクト全ての中身を表示できる。
なお今のところ,このjselectなる関数で指定できるのは
- id
- class
- 親要素関係
- HTML属性
のみ。実用性は乏しい。
さらに改良してselectの入れ子ができたらいいと思う。
今は親要素にIDを指定した場合,その子要素にgetElementsByTagName()をかけるなら
jselect( "select p from #div1" )
と書く必要があるが,例えば,この#div1というjQuery記法をなくすために
jselect( "select p from (select * from document where id = div1)" )
のようにできたら便利だ。( ) 内の一つのselect文が,getElementById() か,getElementsByTagName() に相当するわけだ。
何がしたいのか?
やりたかったのは,「select文の世界で眺めることにより,jQueryでどういう事が実現可能なのかをわかりやすく表現する」ということ。
何か物を探索するとき,DBのように扱えたら楽だろうなと夢見てしまう事がある。
例えば,机の引出しをあけたとき Windows PC内からファイルを探し出すとき。時間指定やファイルサイズ指定など,1つの「select文」をコマンドプロンプトで実行すれば,該当ファイルがごっそりと手に入る。
そんなうまい話は今のところない。
※コマンドプロンプトの限界については,ある程度下記記事で紹介した。
コマンドプロンプトで,暗記するべき10の必須コマンド (前半) ファイル処理系
http://language-and-engineering.hatenablog.jp/entry/20081001/1222857265
しかしDOM要素に対しては,そういったSQLによるかのような便利な抽出が,現在はJavaScriptライブラリを使って実現可能なのだ。
その便利さを,本当にselect文のようなものを使って表現できたら面白いと思った。
追記1
jsonデータに対して,上と同様のselect文のようなものを指定してデータ抽出できるjQueryプラグインが存在する。
SQL調にデータを取得できるJavascript、JsonSQL【jQuery】
http://2-laps.com/mt/2008/02/sqljavascriptjsonsqljquery.html
また、PHPでHTMLを扱う際には、HTMLSQLというのが使える。
HTMLの要素をSQLのように取り出せるPHPのライブラリ『htmlSQL』
http://www.ideaxidea.com/archives/200...