/*-----------------------------------------------------------------*\ | File: MORPHX.as | Author: Samuel Wan | Language: Flash 5 ActionScript | Purpose: Define an object which can load an XML | source, and then convert the source to an | array structure. Each instance of the | MORPHX constructor contains both the | the XML object and the array structure available | as properties of the main object. | | The MORPHX constructor simplifies the | use of XML by making both the original XML | and the converted array structure available to | the user in a single object. As a result, the user | can easily load an XML source, and work more | easily with array structure, while having the original | XML object available at the same time. | | The array structure is located here: myObject.structure | The XML object is located here: myObject.objXML | | Dependancies: none | Original Version: Phil Scott | Modified: Caspar Noetzli August 2002, fixed an error with more than two elements of the same name. Caspar Noetzli May 2004, added functionality: remove processing instructions onData (infopath problem) | Developed: April 2001 | Personal Notes: Thanks to Phil Scott for letting me learn from his deep style. | | Modifications: The original functions were adapted by Samuel Wan | to simplify the algorithm into a single constructor. The algorithms have also | been cleaned up and modified by Samuel Wan to standardize the converted | array structure. | | Example: | For example, you can use the following code to create a new object which | loads the "menu.xml" document from its URL parameter, and then returns an | object that contains both the original XML object and a converted array structure | derived from the XML. The path to the converted array would be | "_root.myObject.structure". | | myObject = new MORPHX("menu.xml"); | myObject.onLoad = function() { | trace("finished loading!"); | } | | Class: "MORPHX" | | Constructor: | var myData = new MORPHX("file.xml"); | | Public Methods: | .onLoad(); | | Public Properties: | .objXML // The original XML object for the XML file. | | .structure // The array object derived from the XML source | | .onLoad // function reference, pointing to a user-defined function | // This is over-written by the user with the same purpose as | // the XML object's .onLoad() method. It triggers code | // as soon as the XML has loaded and conversion has | // occured. | | Private Properties: None | | Private Functions: | initConversion() // Triggered by the XML object's onLoad() method, and | // begins the parseXML recursive function. | | parseXML(array, node) // Accepts XML source and a blank {} hash array, | // and then recursively returns an array object derived | // from the XML source | | Copyright Juxt Interactive, 2001. All Rights Reserved. \*-----------------------------------------------------------------*/ //------------------------------------------------------------------- // Purpose: Constructor called by the user to create a new instance // of this object. It receives the URL of the XML file, and returns an object // containing objXML (the original XML object), and structure (the derived // array object. //------------------------------------------------------------------- function MORPHX(url) { this.objXML = new XML(); this.objXML.ignoreWhite = true; //Define a reference to its parent object this.objXML.parent = this; //this.objXML.onLoad = this.initConversion; // noe this.objXML.onData = this.removeProcessingInstructions this.objXML.load(url); } //------------------------------------------------------------------- // NOE: Purpose: Clean Processing Instructions from raw XML-String //------------------------------------------------------------------- MORPHX.prototype.removeProcessingInstructions = function(rawXMLData_str){ // remove processing instructions var tIndex = (rawXMLData_str.lastIndexOf("?>")) var tCleanedString = rawXMLData_str.slice(tIndex+2) // create clean xml var tCleanedXML_xml = new XML() tCleanedXML_xml.ignoreWhite=true tCleanedXML_xml.parseXML(tCleanedString) // pass on cleaned xml this.parent.initConversion(tCleanedXML_xml) } //------------------------------------------------------------------- // Purpose: Triggered by the XML's onLoad method, and initializes // the parseXML recursive function. // NOE: now triggered by the removeProcessingInstructions function //------------------------------------------------------------------- MORPHX.prototype.initConversion = function(whichXML) { this.structure = this.parseXML({}, whichXML.firstChild); this.onLoad(); }; //------------------------------------------------------------------- // Purpose: A public method which must be over-written by the // user. This method is triggered when the XML has loaded and the // XML-to-array conversion has occured. //------------------------------------------------------------------- MORPHX.prototype.onLoad = function () {}; //------------------------------------------------------------------- // Purpose: A recursive function to parse an XML node into // an arrays structure, and then return the array. //------------------------------------------------------------------- MORPHX.prototype.parseXML = function (structure, node) { //Temporary holder for child nodes, attributes and values. //Once you're done entering data into each new tempObject, //then you insert the tempObject into the actual structure, //depending on whether it's a duplicated array or new array //Using object initializer notation (anonymous object) var tempObject = {}; while(node != null) { //Filter out null-whitespace nodes if(node.nodeType == 1) { //Recursive tempObject = this.parseXML( {}, node.firstChild); //Get the node name to use as the hash name. var name = node.nodeName; //Get all the attributes for(var n in node.attributes) { tempObject[n] = node.attributes[n]; } //Check the first child of the node to see if it's a text node. //If it's a textnode, assign it to the current object's _value property var childNode = node.firstChild; if(childNode != null && childNode.nodeType == 3) { tempObject._value = childNode.nodeValue; } //If the node already exists, make it an array /*if(structure[name] == null) { //It's not an array, so just assign the temporary object to the structure structure[name] = tempObject; } else */ if (structure[name] == null) { structure._type = "array"; //It's not yet an array, so convert to an array and push the temporary object back in. //This is very tricky, because you cannot just use a reference to the element, because //the reference is not a copy of the element, just a pointer to the original array element, //So you must make the object an element of itself by assigning the object to an element //of itself when declared as an array. var t = structure[name]; structure[name] = new Array(); structure[name].push(tempObject); } else { structure[name].push(tempObject); } } node = node.nextSibling; }//while return structure; }