ActionScriptによるXMLデータ処理(1) - XML読み込みと解析
Flash(ActionScript)はXMLオブジェクトやXMLSocketオブジェクトが標準装備されており、ムービー内で必要となる何らかのテキストデータをswfに読み込ませる場合や、swfとサーバーCGIとの間でデータの通信を行う際には、XML形式データを使用するのが便利である。テキストの読み込みはloadVariables関数やLoadVars オブジェクトなどを用いて行うことも可能であるが、これらはマルチバイト文字のエンコードに関して不確実性があり、問題が生じる場合がある。ここではXMLデータをURL(ファイル)またはサーバーCGIから読み込み、その解析を行うコードの実装例を紹介する。
関連項目:ActionScriptによるXMLデータ構築
XMLの読み込み
XMLを読み込むコードは次のようになる。
XMLを単純にファイル(URL)から読み込む場合
// ---- XMLの単純なロード infoXML = new XML(); infoXML.ignoreWhite = true; // 改行などの空白を無視 infoXML.onLoad = function(success) { _root.parseDataXML(success ? this : null);}; infoXML.load("data.xml");
サーバー(CGI)にXMLデータを送信して結果のXMLを受け取る場合
// ---- XMLデータを送信して結果XMLをロード infoXML = new XML(); infoResultXML = new XML(); infoResultXML.ignoreWhite = true; // 改行などの空白を無視 infoResultXML.onLoad = function(success) { _root.parseDataXML(success ? this : null);}; infoXML.sendAndLoad("data.cgi", infoResultXML);
XMLが行末に改行を含む場合、それらはテキストノードデータとして扱われる。それを無視するにはignoreWhiteのプロパティをtrueに設定する。ロードは非同期に行われるため、onLoadイベントハンドラ関数を設定し、読み込み完了時に自動的にXMLデータ解析等の処理を行うように構成する。 onLoad関数内でthisはXMLオブジェクト自体を指すため、他で定義したユーザ関数を呼び出す場合は絶対パスで指定する必要がある。
XMLの解析
XMLはデータ(エレメント)が入れ子になった階層構造(ツリー構造)が特徴であるため、その解析にはスタックと再帰関数を用いるのが常套手段となる。再帰関数によってXMLの全ノードを網羅的にスキャンし、目的とする要素にたどり着いたところで必要なデータを取り込む。
// ---- XML解析 function parseDataXML(infoXML) { if (!infoXML) { trace("XML読み込みエラー"); return; } // ---- データを格納する配列を用意 this.infoData = new Array(); this.infoActiveItem = new Array(); // ---- ルートを起点として解析プロシージャ呼び出し procParseDataXML(infoXML, null); } // ---- XML parser プロシージャ function procParseDataXML(infoXML, infoStack) { if (!infoStack) var infoStack = new Array(); var strNodeName = infoXML.nodeName.toLowerCase(); // ---- ノード名をスタックに積む infoStack.unshift(strNodeName); // ---- XML内でのエレメントの絶対パス取得 var strNodePath = infoStack.join("."); // ---- パス(またはノード名)に応じて必要なデータを取り出す if (strNodePath == "item.data.") { // ---- データ配列に新たな要素を追加 this.infoActiveItem = new Array(); this.infoData.push(this.infoActiveItem); // ---- 属性を全て取得 var strAttribute; for(strAttribute in infoXML.attributes) { this.infoActiveItem[strAttribute.toLowerCase()] =infoXML.attributes[strAttribute]; } } var i; // ---- 子ノード解析 for(i in infoXML.childNodes) { if (infoXML.childNodes[i].nodeType == 3) { // ---- テキストノード this.infoActiveItem[infoStack[0]] += infoXML.childNodes[i].nodeValue; } else { //---- エレメント(関数の再帰呼び出し) procParseDataXML(infoXML.childNodes[i], infoStack); } } // ---- スタックから取り出し&破棄 infoStack.shift(); }
再帰関数を用いる方法は単に数行程度の短いXMLデータを読み込む場合に用いるには、やや冗長な印象もあるが、XMLのノード構成にあわせて解析部をハードコーディングした場合はXMLの構造変化の度にコードを書き換える必要があるのに対し、この方法であればXMLのノードの構成がどんなに変更されても同じコードで対応できる。また、どんなに長いXMLデータでもこの関数一つで処理できるのが利点である。