// MsXML - XML converter and scanner
// Version 0.63
//
// Copyright (C) 2006, Michiel Sikma <michiel@thingmajig.org>
// 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: <![CDATA[(information goes "+
"here)]>>.";
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);
}
}
};