/*-----------------------------------------------------------------*\ | File: CLX_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 | CLX_MORPHX constructor contains both the | the XML object and the array structure available | as properties of the main object. | | The CLX_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) | Andy Haeberli December 2005, added functionality: xmlLoadFile, xmlLoadString | 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 CLX_MORPHX(); | myObject.xmlLoadFile("menu.xml"); | myObject.xmlLoadString(); | myObject.onLoad = function() { | trace("finished loading!"); | } | | Class: "CLX_MORPHX" | | Constructor: | var myData = new CLX_MORPHX(); | | Public Methods: | .xmlLoadFile(URL); | .xmlLoadString(XML); | .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. //------------------------------------------------------------------- function CLX_MORPHX() { this.objXML = new XML(); this.objXML.ignoreWhite = true; // Define a reference to its parent object this.objXML.parent = this; } //------------------------------------------------------------------- // ahae: load raw XML-File // It receives the URL of the XML file, and returns an object // containing objXML (the original XML object), and structure (the derived // array object. //------------------------------------------------------------------- CLX_MORPHX.prototype.xmlLoadFile = function(url) { this.objXML.onData = this.xmlFile_loaded; this.objXML.load(url); }; //------------------------------------------------------------------- // ahae: load raw XML-File (loaded) //------------------------------------------------------------------- CLX_MORPHX.prototype.xmlFile_loaded = function(rawXMLData_str) { this.objXML = rawXMLData_str; this.parent.removeProcessingInstructions(rawXMLData_str); }; //------------------------------------------------------------------- // ahae: load raw XML-String // It receives the XML file, and returns an object // containing objXML (the original XML object), and structure (the derived // array object. //------------------------------------------------------------------- CLX_MORPHX.prototype.xmlLoadString = function(rawXMLData_str) { this.objXML = rawXMLData_str; this.removeProcessingInstructions(rawXMLData_str); }; //------------------------------------------------------------------- // NOE: Purpose: Clean Processing Instructions from raw XML-String //------------------------------------------------------------------- CLX_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.initConversion(tCleanedXML_xml); }; //------------------------------------------------------------------- // Purpose: Triggered by the XML's onLoad method, and initializes // the parseXML recursive function. // NOE: now triggered by the removeProcessingInstructions function //------------------------------------------------------------------- CLX_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. //------------------------------------------------------------------- CLX_MORPHX.prototype.onLoad = function() { }; //------------------------------------------------------------------- // Purpose: A recursive function to parse an XML node into // an arrays structure, and then return the array. //------------------------------------------------------------------- CLX_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; };