// MsXML - XML converter and scanner // Version 0.63 // // Copyright (C) 2006, Michiel Sikma // Dependencies: // CommonFuncts (common.as) - Common functions and prototypes #include "common.as" // xmlToArray function converts raw XML data to objects within arrays. // Usage: // xmlToArray(xmlObject, arrayObject, parseMode) // Parameters: // xmlObject the XML object that has to be converted. // arrayObject the object that is to contain the converted XML data. // legacy whether legacy parsing should occur (ignores node names // when creating object properties; some code relies // on this). // Description: // Takes a raw XML object and converts all the available XML data into // a more accessible object. This will allow you to more easily access the // data of an XML object by usage of object paths rather than the tedious // built-in nodeObject et al. commands. function xmlToArray( xmlObject:XMLNode, arrayObject:Array, legacy:Boolean):Void { for (var a:Number = 0, nodeObject:XMLNode = xmlObject.firstChild; nodeObject != null; nodeObject = nodeObject.nextSibling, a++) { // First off, we must check to see if this node contains child nodes // with the same name. If so, we must suffix these names with a // serial number, and if not, the original names must be preserved. // This entire block is not performed if legacy parsing is // in effect. if (!legacy) { for (var nodeSibling:XMLNode = nodeObject.parentNode.firstChild, nodesUnique:Array = new Array(), nodesCommon:Array = new Array(); nodeSibling != null; nodeSibling = nodeSibling.nextSibling) { if (nodesUnique.exist(nodeSibling.nodeName)) { nodesCommon.push(nodeSibling.nodeName); } else { nodesUnique.push(nodeSibling.nodeName); } } } if (nodeObject.nodeType == 1) { // In case the node is an XML object: // reiterate until it is fully documented. if (!legacy) { if (nodesCommon.exist(nodeObject.nodeName)) { var c = nodeObject.nodeName+"_"+a; } else { var c = nodeObject.nodeName; } } else { var c = a; } arrayObject[c] = {_name:nodeObject.nodeName, _id:a}; objectAttributes = nodeObject.attributes; for (var b in objectAttributes) { // For every attribute in an XML node... if (!(isNaN(Number(objectAttributes[b])))) { // In case this is a number: convert it from // string to number... arrayObject[c][b] = Number(objectAttributes[b]); } else if (objectAttributes[b] == "true") { // ... or perhaps it's a true boolean... arrayObject[c][b] = true; } else if (objectAttributes[b] == "false") { // ... or perhaps it's a false boolean... arrayObject[c][b] = false; } else { // ... or else: leave it alone. arrayObject[c][b] = objectAttributes[b]; } } // Reiterate this code to continue with the next object. xmlToArray(nodeObject, arrayObject[c], legacy); } else { // In case the node is a text object: store the text // in a node and stop iterating this path. arrayObject["_value"] = nodeObject.nodeValue; } } if (a > 0) { // As long as there is more than one child node: update the length // of its parent node. arrayObject._length = a; } }; // xmlInitialize function loads an XML file and processes it. // Usage: // xmlInitialize(xmlFile, xmlArray, callbackSuccess, callbackFailure) // Parameters: // xmlFile the file that has to be loaded and converted. // xmlArray the object that is to contain the resulting data. // callbackSuccess the function that is called after the XML // successfully loads. // callbackFailure the function that is called after the XML // fails to load. // legacy whether legacy parsing should occur (ignores node // names when creating object properties; some code // relies on this). Used just for xmlToArray(); // Description: // Takes an XML file and loads it into a temporary object which is then // converted to an array with xmlToArray(). After this is done, a user- // specified function is called; either the one in the case of success or // the one for failure. The failure callback is called // with three arguments: a returned error number, a string explaining // the problem, and a concatenation of these two things (for those who // are too lazy to do it themselves). function xmlInitialize( xmlFile:String, xmlArray:String, callbackSuccess:Function, callbackFailure:Function, legacy:Boolean):Void { var xmlObject:XML = new XML(); xmlObject.ignoreWhite = true; xmlObject.onLoad = function(success:Boolean):Void { if (success && xmlObject.status == 0) { if (!root) _global.root = _root; root[xmlArray] = new Object; xmlToArray(this, root[xmlArray], legacy); callbackInterval = setInterval(function() { callbackSuccess(); clearInterval(callbackInterval); }, 250); } else { var errorNumber:Number = xmlObject.status; var errorMessage:String; if (errorNumber == -2) errorMessage = "One or more CDATA sections were not properly "+ "terminated. Ensure that all CDATA sections are "+ "formed like this: >."; if (errorNumber == -3) errorMessage = "The XML declaration was not properly terminated."; if (errorNumber == -4) errorMessage = "The DOCTYPE declaration was not properly terminated."; if (errorNumber == -5) errorMessage = "A comment was not properly terminated."; if (errorNumber == -6) errorMessage = "An XML element was malformed."; if (errorNumber == -7) errorMessage = "XML file too large; the Flash player's XML parser "+ "threw an \"out of memory\" exception."; if (errorNumber == -8) errorMessage = "One or more attribute values were not properly "+ "terminated."; if (errorNumber == -9) errorMessage = "One or more start tags were not matched with a "+ "proper end tag."; if (errorNumber == -10) errorMessage = "One or more end tags without a matching start tag "+ "were encountered."; else errorMessage = "An unknown error has occurred; does the XML "+ "file exist?"; var errorCat:String = "Error -"+errorNumber+": "+errorMessage; callbackInterval = setInterval(function() { callbackFailure(errorNumber, errorMessage, errorCat); clearInterval(callbackInterval); }, 250); } }; // After defining the parse actions, we can load the file. xmlObject.load(xmlFile); } // scan function traces the contents of an XML object converted with // xmlToArray for debugging purposes. // Usage: // scan(arrayObject) // Parameters: // arrayObject the object that to contains the converted XML data. // Description: // Traces the entire XML array and return its data tree for debugging // purposes. Do not use this function without first converting the XML // into an array with xmlToArray; otherwise, it will be infinitely // recursive. function scan(obj:Object, t:String):Void { if (t == undefined) { var t:String = "+ "; } t = "|\t"+t; for (var a in obj) { trace(t+a+" = "+obj[a]); if (typeof obj[a] == "object" || typeof obj[a] == "array") { // Reiterate this code to continue with the next object. scan(obj[a], t); } } };