linq.js to Linq to XML/DOM

Linq to Xmlの移植を始めました。やはりJavaScript上で最も動かすことになるリストってDOMなので、欠かかせません←結論。これで大幅に使い道や表現の幅が広がりそうです。ただ、あまりやり過ぎるとjQueryでいいぢゃん、的な捉えられかたをされてしまいそう。個人的には全然用途が違う、共存できるものだと思っているのだけど。

前回書いたC#でのLinq to Xml例と比べても、ほとんど書き方は一緒です。linq.jsではLinq.EnumerableのショートカットとしてEを使いましたので、今回はLinq.XElementのショートカットとしてXを使うことにしました。アルファベット一字系はちょっと危険かなあ、というところがあるので要再検討、でしょうか。

値を得るValue()は、キャストのかわりにパースする関数を引数で取るようにしました。Value(parseInt)で数字が取れるわけです。カッコが一つ減って、少し見通しが良くなる。地味に便利です。多分。あと、Value()で取れる値はIEのinnerTextと同じです(多分) FirefoxでinnerTextが使える!というのは利点にならないでしょうかならないですか。取得専用だし。

実際の書き方ですけど、div->h1,h2,h3は見たまんまにシンプルなのですが、p->textのほうはちょっと複雑になってしまいました。慣れないと若干厳しめ? SelectManyはノード操作時に便利です。Elements("p")だけでは、1個のpタグのノードしか取得できないので、更に展開するためにSelectManyを使います。展開するものの指定は、childNodeを取りたいので$.Elements()。引数(タグ名)無しだとchildNodeを全て展開します。これで[tako,br,huga,br,hoge,br]というXElementが取得できます。第二引数はresultSelectorということで、平坦化の後の射影です。今は値が欲しいだけなので、Value()を利用。これで結果は[tako,null,huga,null,hoge,null]になりました。nullは、brタグのValueです。これはいらないので、最後にWhereで除去してやれば出来あがり。

Elements: function(name)
{
    var base = Linq.Enumerable.From(this.Source.childNodes)
        .Select(function(elem) { return new Linq.XElement(elem); });

    return (name == null)
        ? base
        : base.Where(function(elem) { return elem.Source.nodeName === name.toUpperCase(); });
},

Elementsのソースコードは今のところこんな感じです。Linq to Objectsという基盤があるので、それを適用することに特化したDOM Elementのラッパー、ということになります。C#のLinq to Xmlがそうであるように、取得だけじゃなくて、反映までやりたいですねえ。とりあえず、今のままでもXMLのパースぐらいになら十二分に使えると思うので、linq.jsの次回更新時にテスト版として入れときます。

Profile

Yoshifumi Kawai

Cysharp, Inc
CEO/CTO

Microsoft MVP for Developer Technologies(.NET)
April 2011
|
July 2025

X:@neuecc GitHub:neuecc

Archive