XMLを使ってみる(その5)
50分の3
「ActionScript 3 がイケてる50の理由 : Media Technology Labs (MTL)」というblogを読んで、「fifty reasons ActionScript 3 kicks ass」というスライドを知りました。
ActionScript3が素晴らしい具体的な理由を50個あげているのですが、その#36から#38がE4Xの紹介に割り当てられていました。
ちょっとそのスライドを見ながらをE4Xの扱い方をおさらいしつつメモしたいと思います。
#36: E4X: Inline XML, with variables
var myXML:XML = <xml> <item id="20" varAtt={myVar} /> <item>{value}</item> {myOtherXML} </xml>;
「XMLを使ってみる(その2)」で紹介した「XMLリテラルの中で式を評価」という機能の紹介ですね。
XMLに自由に変数を組み込めるのがとても便利、という話。
上記のXMLの例で言えば、例えば、このとき、
var myVar:int=2008; var value:String="Memo String"; var myOtherXML:XML=<item id="21" varAttr={myVar+12} />;
という変数が事前に設定してあれば、trace( myXML.toXMLString() ) の出力結果は次のような内容になります。
[trace] <xml> [trace] <item id="20" varAtt="2008"/> [trace] <item>Memo String</item> [trace] <item id="21" varAttr="2020"/> [trace] </xml>
#37: E4X: Powerful filtering
// get all item nodes // where id attribute == val: myXML..item.(@id == val) // supports RegExp: myXML..item.(/^Mc/.test(@name))
myXML..ってなんだ?これはタダのタイプミスですね、多分。(2008-07-16 タイプミスではありませんでした。myXML..itemというのはmyXML以下のitemノードを再帰的に取得したXMLListになるのですが、このサンプルでは1階層しかないのであまり意味がありません。)
まず1つめですが、アトリビュートで簡単にフィルタリングしてXMLListを取得できるので便利、という話。以下のコードで試してみます。
var itemXML:XML = <xml> <item id="1" name="one" /> <item id="1" name="two" /> <item id="1" name="three" /> <item id="2" name="four" /> </xml>; var pickedItems:XMLList = itemXML.item.(@id==1); trace( pickedItems.toXMLString() );
以上のコードを実行すると次のように出力されます。
[trace] <item id="1" name="one"/> [trace] <item id="1" name="two"/> [trace] <item id="1" name="three"/>
ただし、例えば
[フォルト] exception、情報 =ReferenceError: Error #1065: 変数 @id は定義されていません。 理由 : Fault、関数名 : test4()、場所 : TestXML.as:46 46 var pickedItems:XMLList = itemXML.item.(@id==1);
2つめは、アトリビュートのフィルタリングに正規表現も使える、という話ですね。
先ほどの例のpickedItemsを選び出すところを次のコードに置き換えて実行してみます。
var pickedItems:XMLList = itemXML.item.(/o/.test(@name));
nameアトリビュートにoが入っている項目を抜き出す、という処理なのですが、出力は以下のようになり意図通りにピックアップされました。
[trace] <item id="1" name="one"/> [trace] <item id="1" name="two"/> [trace] <item id="2" name="four"/>
#38: E4X: XML manipulation
// append a new child node: myXML.* += <item id='13' /> // remove child node with id 12: delete(myXML.item.(@id == 12)[0]) // insert before second node: myXML.*[1] = <item/> + myXML.*[1]
まず、一つめ。
myXML.* で表されるトップノードの子ノードリストに追加することになるので、子ノードの最後に追加されます。以下のコードで確認してみます。
var itemXML:XML = <xml> <item id="1" name="one" /> <item id="1" name="two" /> <item id="2" name="four" /> </xml>; itemXML.* += <item id='13' />; trace( itemXML.toXMLString() ); // ついでに、itemXML.* が何ものであるのかを出力. trace( getQualifiedClassName( itemXML.* ) );
次のように出力され、最後に
[trace] <xml> [trace] <item id="1" name="one"/> [trace] <item id="1" name="two"/> [trace] <item id="2" name="four"/> [trace] <item id="13"/> [trace] </xml> [trace] XMLList
なるほど、何となく仕組みが分かってきたので、続いて次のコードを試してみます。
// アトリビュートが一致した一つめを削除. delete( itemXML.item.(@id == 1)[0]); trace( "check -- 1\n" + itemXML.toXMLString() ); // 置換. itemXML.*[1] = <item id='7' /> trace( "check -- 2\n" + itemXML.toXMLString() ); // [1]の後に挿入. itemXML.*[1] += <item id='8' /> trace( "check -- 3\n" + itemXML.toXMLString() );
これらは次のように出力されます。
[trace] check -- 1 [trace] <xml> [trace] <item id="1" name="two"/> [trace] <item id="2" name="four"/> [trace] <item id="13"/> [trace] </xml> [trace] check -- 2 [trace] <xml> [trace] <item id="1" name="two"/> [trace] <item id="7"/> [trace] <item id="13"/> [trace] </xml> [trace] check -- 3 [trace] <xml> [trace] <item id="1" name="two"/> [trace] <item id="7"/> [trace] <item id="8"/> [trace] <item id="13"/> [trace] </xml>
E4Xって、演算子でいろいろな操作ができ、かなり自由度が高いことをやれる仕組みですね。超便利!これは一度使ったら従来の(ActionScript2.0以前の)XML操作には戻れそうにありません。