最初に XML を拾って解析してみる。
tags.xml
<?xml version="1.0" encoding="utf-8" ?> <tags> <tag id="0" name="猫" /> <tag id="1" name="犬" /> <tag id="2" name="動物" /> </tags>
contents.xml
<?xml version="1.0" encoding="utf-8" ?> <contents> <item title="窓辺の淑女" url="image/sample.jpg" thumb="thumb/sample.jpg"> <tag id="0" /> <tag id="2" /> <comment> <![CDATA[ 窓辺にたたずむ優雅な猫。 ]]> </comment> </item> </contents>
モデルデータの実態はこんなフォーマットで良いかな。
XML を読み込む手順が以下。
public class XMLConfigLoader extends EventDispatcher { private var request:URLRequest; private var loader:URLLoader; private var xmlData:XML; public function XMLConfigLoader(targetUrl:String) { this.request = new URLRequest(targetUrl); this.loader = new URLLoader(this.request); this.loader.addEventListener(Event.COMPLETE, this.loadongEvent); this.loader.addEventListener(IOErrorEvent.IO_ERROR, this.loadongEvent) this.loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, this.loadongEvent); } public function load():void { this.loader.load(this.request); } private function loadongEvent(event:Event):void { switch(event.type) { case Event.COMPLETE: this.xmlData = new XML(event.target.data); dispatchEvent(event); break; case IOErrorEvent.IO_ERROR: case SecurityErrorEvent.SECURITY_ERROR: dispatchEvent(new Event(Event.CANCEL)); break; } } public function get xml():XML { return this.xmlData; } }
XML の読み込み処理があまりにも定型句なので、こんなクラスを作って簡略化。
しかし、、、、tags は別に Dictionary で key = value にしとけばいいとして、問題は contents だ。
こんなの実行時に生データで弄ってらんない。
public class ContentItem { private var _title:String; private var _url:String; private var _thumb:String; private var _tag:Array; private var _comment:String; public function ContentItem(xml:XML, tags:Object) { this._title = xml.@title; this._url = xml.@url; this._thumb = xml.@thumb; this._comment = xml.@comment; this._tag = []; var tagList:XMLList = xml.tag; for each(var target:XML in tagList) { var id:int = target.@id; this._tag.push(tags[id]); } } /* get/set は略 */ }
こんなんを書いておく。
そして、設定ファイルローダを作る。
public class ConfigLoader extends EventDispatcher { private var tagLoader:XMLConfigLoader; private var contentLoader:XMLConfigLoader; public function ConfigLoader() { // ファイルのロード準備 this.tagLoader = new XMLConfigLoader("tags.xml"); this.contentLoader = new XMLConfigLoader("contents.xml"); } public function load():void { // 両方ロードが完了した時点でイベント通知。 var completeCount:int = 0; var callCount:int = 0; // 各ファイルのロード完了、もしくは失敗時の処理 var result:Function = function(eve:Event):void { callCount++; switch(eve.type) { case Event.COMPLETE: completeCount++; break; case Event.CANCEL: break; } // 全ファイル正常読み込み完了 if (callCount == 2 && completeCount == 2) dispatchEvent(eve); // 1 個以上読み込み失敗 if (callCount == 2 && completeCount != 2) dispatchEvent(new Event(Event.CANCEL)); // 読み込み結果取得完了時に、イベントリスナ開放。 if (callCount == 2) { tagLoader.removeEventListener(Event.COMPLETE, arguments.callee); contentLoader.removeEventListener(Event.COMPLETE, arguments.callee); tagLoader.removeEventListener(Event.CANCEL, arguments.callee); contentLoader.removeEventListener(Event.CANCEL, arguments.callee); } }; // イベントリスナを仕掛ける。 tagLoader.addEventListener(Event.COMPLETE, result); contentLoader.addEventListener(Event.COMPLETE, result); tagLoader.addEventListener(Event.CANCEL, result); contentLoader.addEventListener(Event.CANCEL, result); // ローディング開始 this.tagLoader.load(); this.contentLoader.load(); } private var _tags:Object = null; public function get tags():Object { // 初回取得時に xml 解析 if (this._tags == null) { var tagXML:XML = this.tagLoader.xml; var lists:XMLList = tagXML.tag; this._tags = {}; for each(var target:XML in lists) { var id:String = target.@id; var name:String = target.@name; this._tags[id] = name; } } return this._tags; } private var contents:Object = null; public function getContentsByTag(tagId:String):Array { // 初回取得時に xml 解析 if (this.contents == null) { this.contents = { }; var tagXML:XML = this.contentLoader.xml; var lists:XMLList = tagXML.item; // タグごとに配列を準備 var taglist:Object = this.tags; for (var index:String in taglist) this.contents[taglist[index]] = []; this.contents["allContents"] = []; // アイテム解析、登録 for each(var target:XML in lists) { var item:ContentItem = new ContentItem(target, taglist); var instag:Array = item.tag; this.contents["allContents"].push(item); for each(var ins:String in instag) this.contents[ins].push(item); } } return this.contents[tagId]; } }
設定ファイルのサイズが大きくなって、タグごとにファイルが分離する場合も、この設定ローダで吸収しておけばよさげ。
そして、実際に走らした。
<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" width="1024" height="700" backgroundColor="#442222" creationComplete="initializer()"> <fx:Declarations> <!-- Place non-visual elements (e.g., services, value objects) here --> </fx:Declarations> <fx:Script> <![CDATA[ import flash.events.Event; import mx.containers.Canvas; import net.azaleaworks.utils.XMLConfigLoader; import photo.ConfigLoader; import flash.utils.describeType; import photo.ContentItem; private var tags:ConfigLoader; private function initializer():void { tags = new ConfigLoader(); tags.addEventListener(Event.COMPLETE, this.completeHandler); tags.load(); } private function completeHandler(event:Event):void { // チェック var contents:Array = this.tags.getContentsByTag("allContents"); var item:ContentItem = contents[0]; trace(item.title); } ]]> </fx:Script> <mx:TabNavigator width="100%" height="100%" id="tabNav"> <mx:Canvas width="100%" height="100%" label="全般" id="allContents" /> </mx:TabNavigator> </s:Application>
FlashDevelop でブレークできないの初めて知った、、、、。
プラグインが出てるけど、最新版のFlashDevelopとは相性が悪いようだ。*1
http://orange.zero.jp/zbn39616.pine/download/download.html
*1:推奨 3.0 で FlashDevelop 最新が 3.1.1