• Coding
  • [Actionscript] XMLManager Class

package com.prodouble-d.util
{
	import flash.events.Event;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	
	public class XMLManager
	{
		private var xmlFile:String;
		private var ldr:URLLoader;
		private var req:URLRequest;
		private var xmlData:XML;
		//private var list:XMLList;
		
		public function XMLManager(file:String):void
		{
			xmlFile = file;
			ldr = new URLLoader();
			req = new URLRequest(xmlFile);
			ldr.addEventListener(Event.COMPLETE, xmlLoaded);
			ldr.load(req);
		}
		
		private function xmlLoaded(e:Event):void
		{
			xmlData = new XML(e.target.data);
		}
		
		public function set file(str:String):void
		{
			xmlFile = str;
		}
		
		public function get data():XML
		{
			return xmlData;
		}
	}
}
Ok so I've got this class so far. I'm not sure whether it's a good idea to generate the XMLList inside the class (and if it is, how do I choose which node of the xml file? shall I use the XMLNode Class?) or do I just feel glad with what I have so far and then generate the list as follows:
var manager:XMLManager = new XMLManager("xmlfile.xml");
var list:XMLList = new XMLList(manager.data.someNode);
I hate the word Manager. It's extremely unspecific and gives carte blache to do anything inside that manager.
You should try and limit yourself instead, perhaps create an XMLLoader. Make sure it dispatches events so that you know when it completes or not.

XMLNode class is deprecated. Adobe recommends using the E4X classes (i.e. XML and XMLList). In this case you should be using XML.

Hope this helps.
arithma wroteMake sure it dispatches events so that you know when it completes or not.
That explains why manager.data is returning null. So in the xmlLoaded method I should dispatch an event and then capture it in the Document Class?
Exactly.
I once thought about implementing this class, but all it saves me really is a single line:
var xmlData:XML = new XML(e.currentTarget.data);
So I don't use an XMLLoader. If you insist, then you should provide the loader's functionality..
To dispatch:
dispatchEvent(new Event(Event.COMPLETE));
And make sure your class is a descendant of EventDispatcher
hmmm I see... but how do I listen on this dispatched event from my document class?
I tried that but didn't work...
private function populateCounList():void
		{
			manager = new XMLManager("countries.xml");
			manager.data.addEventListener(Event.COMPLETE, dataReady);
		}
			
		private function dataReady(e:Event):void
		{
			var dp:DataProvider = new DataProvider();
			var list:XMLList = new XMLList(e.target.country);
			for (var i:uint = 0; i < list.length(); i++)
			{
				dp.addItem( { label: list[i] } );
			}
			countryList.dataProvider = dp;
		}
Try to debug with traces. It should not fail. One reason I could think of is perhaps the Loader is completing before the event listener is even being registered.
Ok here's how I'm doing it now:

XMLManager:
package 
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	
	public class XMLManager extends EventDispatcher
	{
		private var xmlFile:String;
		private var ldr:URLLoader;
		private var req:URLRequest;
		private var xmlData:XML;
		
		public function XMLManager(file:String):void
		{
			xmlFile = file;
			ldr = new URLLoader();
			req = new URLRequest(xmlFile);
			ldr.addEventListener(Event.COMPLETE, xmlLoaded);
			ldr.load(req);
		}
		
		public function xmlLoaded(e:Event = null):void
		{
			xmlData = new XML(e.target.data);
			dispatchEvent(new Event(Event.COMPLETE));
		}
		
		public function set file(str:String):void
		{
			xmlFile = str;
		}
		
		public function get data():XML
		{
			return xmlData;
		}
	}
}
Document Class:
		private function populateCounList():void
		{
			manager = new XMLManager("countries.xml");
			manager.xmlLoaded().addEventListener(Event.COMPLETE, dataReady);
		}
			
		private function dataReady(e:Event):void
		{
			xmlData = e.target.data;
			var dp:DataProvider = new DataProvider();
			var list:XMLList = new XMLList(xmlData.country);
			for (var i:uint = 0; i < list.length(); i++)
			{
				dp.addItem( { label: list[i] } );
			}
			countryList.dataProvider = dp;
		}
This is the error am getting:
1061: Call to a possibly undefined method addEventListener through a reference with static type void.
manager.addEventListener(Event.COMPLETE, dataReady);
Read the Essential Actionscript 3.0, section: Events - not necessarily display list events...
That actually worked! I did some research on the subject and I saw someone adding the listener to the function, so I thought I should do the same. Anyway, thanks a lot, appreciated :)