- 2007-07-23 (月)
- action script
チュートリアルビデオ中でも解説していますが、しつこくテキストでも紹介しておきます。
以前 XPath4AS2 の解説 で使った XML ファイル を流用して、CASA framework ではどうやるのかを紹介していきます。
また、今回以降、XmlUtil クラスを使ってパースしたデータの格納先を Object 型ではなく Array 型にするようにしました。詳細は以下。
サンプルに使用する XML ファイルは以下:
<?xml version="1.0" encoding="UTF-8"?> <foods> <food category="フルーツ"> <name>りんご</name> <place>青森</place> <price>100円</price> </food> <food category="フルーツ"> <name>みかん</name> <place>愛媛</place> <price>80円</price> </food> <food category="野菜"> <name>ゴーヤ</name> <place>沖縄<city>那覇</city></place> <price>70円</price> </food> <food> <name>うどん</name> <place>香川</place> <price>100円</price> <description>ネットで評判のおいしいうどんです。</description> </food> </foods>
という XML ファイルをロード&パースする設定で説明していきます。
1. FLA ファイル内に記述する時のテンプレ
(使用ファイル:inline.fla)
ルートの第1フレームスクリプトに以下のように記述して下さい。
import org.casaframework.load.data.xml.XmlLoad; import org.casaframework.util.XmlUtil; /* いろんな場所から参照するので _root のインスタンスプロパティにしておく */ var foodInfo:Array; /* ロードできたXMLをパース(2) */ function onDataLoad(sender:XmlLoad):Void { // XmlUtil で XML をパース foodInfo = XmlUtil.xmlToObject(this.myXmlLoad.getXml())['foods'][0]['food']; // init を実行 init(); } /* XMLをロード(1) */ //XmlLoadインスタンスの生成と、ロードするxmlファイルのURI指定 var myXmlLoad:XmlLoad = new XmlLoad("foodData.xml"); //ロード完了時の処理 this.myXmlLoad.addEventObserver(this, XmlLoad.EVENT_LOAD_COMPLETE, "onDataLoad"); //ロード開始 this.myXmlLoad.start(); /* パースできたXMLと戯れる(3) */ function init():Void{ //この中に命令を記述していきます trace(foodInfo[0].name[0].nodeValue); }
ロードして(1)→パースして(2)→戯れる(3)の順で実行されるのですが、上のコードでは(2),(1),(3)の順に記述されています。これは、インラインに書いたコードは上から実行されるので(ですよね?)、this.myXmlLoad.start(); で実際にロードを開始する前に、完了時の振る舞いをしっかり認識完了しておけるための配慮です。まぁ実際は、外部XMLをロードする時間のうちに、このフレームスクリプトぐらいは全部読んでいるのですが、念のためです。一般に、そういう書き方があるので、必ずしも「コードは上から実行順に書かれている」ことはないことを心に留めておきましょう。
で、次に紹介する外部クラスを使う手法は、as全体を予めロードしておかないと開始しないので、(1),(2),(3)の順でもOKってことでしょうか。
2. 外部 as クラスに記述する時のテンプレ
(使用ファイル:External.as, external.fla)
まず最初に、External.as(先頭が大文字であれば名前は任意でOK) というクラスファイルを作り、以下のように記述。
import org.casaframework.load.data.xml.XmlLoad; import org.casaframework.util.XmlUtil; class External extends MovieClip {
/* _rootをこのクラスのインスタンスにするメソッド。このメソッドを.flaの_rootから呼ぶ */ static public function main(target:MovieClip):Void { target.__proto__ = External.prototype; Function(External).apply(target, null); } /* インスタンスプロパティ */ private var _xmlLoad:XmlLoad; public var foodInfo:Array; /* コンストラクタ関数 */ function External() { this.loadXML(); } /* XMLをロード(1) */ private function loadXML():Void { //XmlLoadインスタンスの生成と、ロードするxmlファイルのURI指定 this._xmlLoad = new XmlLoad('foodData.xml');
//ロード完了時の処理 this._xmlLoad.addEventObserver(this, XmlLoad.EVENT_LOAD_COMPLETE, 'onXmlLoad'); //ロード開始 this._xmlLoad.start(); } /* ロードできたXMLをパース(2) */ private function onXmlLoad():Void { // XmlUtil で XML をパース this.foodInfo = XmlUtil.xmlToObject(this._xmlLoad.getXml())['foods'][0]['food']; // init を実行 this.init(); } /* パースできたXMLと戯れる(3) */ private function init():Void { //この中に命令を記述していきます trace(foodInfo[0].name[0].nodeValue); } }
次に、まず確認ですが、「flaファイルの _root は MovieClip クラスのインスタンスである」という概念はご理解いただいてますでしょうか。「ムービークリップ」として作ったライブラリの中のシンボルと同様、_root にもタイムラインや深度があることから、_root もMovieClip であることはあきらかですね。
そこで、次に fla ファイルの _root を MovieClip インスタンスから、External クラスのインスタンスに変身(参考記事)させます。(External クラスは MovieClip クラスを 継承(extends)しているので MovieClip としての機能も引き続き使えます→MovieClip + 先ほど定義した Exteranal クラスの機能も併せ持てるわけです)。
_root の 1フレーム目に、以下のように記述:
External.main(_root);
以上、2パターン(fla の _root にインライン記述する方法と、MovieClip クラスを継承させた外部クラスを作り、_root をそのクラスのインスタンスにする方法)の設定完了。次に、各ファイル内の「//この中に命令を記述していきます」の下の行をいろいろいじって、各要素(ノード)や属性値(アトリビュート)へのアクセス方法を見ていきます。
各要素(ノード)や属性値(アトリビュート)へのアクセス方法
上記2アプローチのどちらでもいいので、指定の場所に以下のコードをコピペするなりして、試してみて下さい。まずはサンプルコードそのまま:
trace(foodInfo[0].name[0].nodeValue); 出力:りんご
foodInfo の0番目、つまり1つ目の food ノード、その name ノード(ここでも0番目指定が必要なので注意)のnodeValue(中身)ということで、「りんご」と出力されます。foodInfo[0] の数字を増やしていくと、それに応じて次の food ノード中の名前が見れることを確認してください。
trace(foodInfo[0].category);
//出力結果:フルーツ
これで0番目、つまり1個目の food ノードの category 属性の値を取得できます。
trace(foodInfo[0]length; //出力結果4
food ノードの個数を取得できます。ここで注意。length プロパティといえば Array クラスですが、これまで僕のビデオチュートリアルでは「var xmlObject:Object;」と、Object 型で宣言していました。Object 型のままでも length が取得できていたのと、CASA のクラス名が「XmlToObject」で、CASAドキュメント中でも Object 型で宣言していたので、それに倣って Object にしていたのですが、この前いただいた質問への回答を探していた際、FlashPlayerのパフォーマンス向上のためには「Objectの使用はできるだけ避ける(リンク先記事中の visitor3 のコメント)」という情報を見つけ、これは Array 型にしておいた方が良いと結論付けました。「大阪てら子」でのさくーしゃさんのサンプルも Array 型を使われてましたね。それに倣い、"xmlObject"というありきたりな名前ではなく、「(配列に取得したノード名)+(Info)」という命名ルールを設定しました。今回の場合は、foodノードを格納しているので、foodInfo となるわけです。前回のホットペッパーのサンプルなら shopInfo ですね。
for(var i:Number = 0; i<foodInfo.length; i++){ trace(foodInfo[i].place[0].nodeValue); //出力結果:青森 愛媛 沖縄 香川 }
length が分かるということは、上のように for 文を使ってパースできるというわけです。
以上、一見比較してみると「XPath4AS2」の方が、いろいろとできて便利そうですが、僕の過去経験上、XPath4AS2 で selectNodes メソッドを2回連続で呼んだら Player が一瞬無反応になったので、怖くて使用を避けるようになりました(僕の使い方がまずかったのでしょうか?)。現状、AS2でXMLをロード&パースするなら CASA を使うのが良いのではないかと考えています。AS3なら、標準でXMLの処理が強化されているので、話は変わってきます。
今回使用したファイル一式(fla8形式)を公開しておきます。ご自由にどうぞ。
- Newer: ActionScript3.0 の勉強
- Older: ビデオチュートリアル:CASA の LoadGroup で画像をまとめてをロード
Comment:3
- cyo 2007-07-24 (火) 10:40
-
http://five3d.mathieu-badimon.com/
こういうクラスライブラリがあるみたいですが、知ってましたか?自分はこれからいじってみようと思ってます。
もし、ドキュメントを翻訳する時間などあれば…w - ysp 2007-07-25 (水) 15:58
-
いつも勉強させてもらってます。
おかげさまでCASAをようやくかじれました。
いじってるうちに、はまってしまった事があります。
名前空間のあるRSS、例えば、
<image:thumbnail url="hogehoge" >
こういった物の要素を取り出す場合はどのように記述すればいけるのでしょうか?
xmlObject.image":"thumbnail[0].url
xmlObject."image:thumbnail"[0].url
という風に記述してもダメなんです。
良かったらご教授くださいませ。
よろしく御願いします。 - tera 2007-07-25 (水) 16:28
-
>ysp様
こんにちは。コメントありがとうございます。
ちょっと試してみた所、
xmlObject[0]["image:thumbnail"][0].url
でいけたっぽいので、お試しください。あと、お送り頂いたソースの、xmlObject の部分に、ノード番号([0]とか)が付いていないようですので、そちらも併せてご注意くださいませ。
Trackback:0
- TrackBack URL for this entry
- http://www.trick7.com/blog/mt-tb.cgi/588
- Listed below are links to weblogs that reference
- CASA の XmlLoad, XmlUtil クラスの使い方 from trick7.com blog



