import fv.utils.Delegate; /** Loads an XML document and parses the data contained within the file into an array data structure for easy access. Supports the sending of POST data for use with dynamic XML documents. */ class fv.XMLParser { /** Invoked when the XML document has been parsed successfully after loading. @params data:Array - see data */ public function onLoad(data:Array):Void {} /** Invoked if the XML document could not be loaded or parsed successfully. @params code:Number - A quantitative representation of the error that has occured. message:String - A qualitative representation of the error that has occured. The following are the 11 possible error codes with their respective error messages: -1 : The XML document could not be loaded. -2 : A CDATA section was not properly terminated. -3 : The XML declaration was not properly terminated. -4 : The DOCTYPE declaration was not properly terminated. -5 : A comment was not properly terminated. -6 : An XML element was malformed. -7 : Out of memory. -8 : An attribute value was not properly terminated. -9 : A start-tag was not matched with an end-tag. -10 : An end-tag was encountered without a matching start-tag. default : An unknown error has occurred. */ public function onError(code:Number, message:String):Void {} private var __data:Array; /** The data extracted from the loaded XML document represented as an Array. @usageNote Child nodes are accessed as elements of the node Array (node[ChildNodeIndex]) and attributes are accessed as properties of the node Array (node[attributeName]). */ public function get data():Array { return __data; } private var __thisObject:Object; private var __callback; private var __lv:LoadVars; private var __xml:XML; private var __status:Number; /** @params url:String - The URL of the XML document to be loaded. queryObject:Object (optional) - An object whos enumerable variables are concentrated into a string and posted to the URL using the HTTP POST method. thisObject:Object (optional) - The object that will be referenced whenever the keyword "this" is used in the body of the callback function. callback:Mixed (optional) - The function that will be executed after the XML document has been parsed. The parsed data will be passed as a parameter to this function. @usageNote The method parameter can either be a String or a Function. If a String is passed, the method of the same name assigned to the thisObject will be executed (thisObject[method]). @example var input = new Object(); input.page = 2; input.category = "music"; var xml = new XMLParser("data.xml", input); xml.onLoad = function(data:Array):Void { trace(data); } */ function XMLParser(url:String, queryObject:Object, thisObject:Object, callback) { System.useCodepage = true; __thisObject = (thisObject == undefined ? this : thisObject); __callback = (callback == undefined ? "onLoad" : callback); if (url.indexOf("www.") != -1 && _root._url.indexOf("www.") == -1) { url = url.split("www.").join(""); } __xml = new XML(); __xml.ignoreWhite = true; __xml.onLoad = Delegate.create(this, "onData"); __lv = new LoadVars(); for (var name in queryObject) { var value = queryObject[name]; if (value != undefined) __lv[name] = value; } __lv.sendAndLoad(url, __xml); } private function onData(success:Boolean):Void { delete __lv; try { if (!success) __status = -1; else __status = __xml.status; if (__status != 0) throw new Error(errorMessage(__status)); } catch(error:Error) { trace(error.message); onError(__status, error.message); } finally { if (__status == 0) { var callback = (typeof __callback == "string" ? __thisObject[__callback] : __callback); __data = parseNode(__xml.firstChild); callback.apply(__thisObject, [__data]); } } } private function parseNode(xml):Array { var attributes = xml.attributes; var childNodes = xml.childNodes; var data = new Array(); for (var i in attributes) { data[i] = parseValue(attributes[i]); } for (var i = 0; i < childNodes.length; i++) { var childNode = childNodes[i]; if (childNode.nodeType == 3) { data.push(parseValue(childNode.nodeValue)); } else { data.push(parseNode(childNode)); data[childNode.nodeName] = data[i]; } } return data; } private function parseValue(value) { if (value == "true" || value == "false") return value == "true"; if (!isNaN(value)) return Number(value); return value; } private function errorMessage(status:Number):String { switch (status) { case -1 : return "The XML document could not be loaded." case -2 : return "A CDATA section was not properly terminated."; case -3 : return "The XML declaration was not properly terminated."; case -4 : return "The DOCTYPE declaration was not properly terminated."; case -5 : return "A comment was not properly terminated."; case -6 : return "An XML element was malformed."; case -7 : return "Out of memory."; case -8 : return "An attribute value was not properly terminated."; case -9 : return "A start-tag was not matched with an end-tag."; case -10 : return "An end-tag was encountered without a matching start-tag."; default : return "An unknown error has occurred."; } } private function toString():String { return __xml.toString(); } }