/* Wddx Serializer/Deserializer for Flash MX 2004 v1.0 Coded to work with ActionScript 2.0 -------------------------------------------------- Created by Branden Hall (bhall@waxpraxis.org) Dave Gallerizzo (dgallerizzo@figleaf.com) Based on code by Simeon Simeonov (simeons@allaire.com) Nate Weiss (nweiss@icesinc.com) Version History: 8/10/2000 - First created 9/5/2000 - Minor bug fix to the deserializer 9/15/2000 - Commented out Wddxserializetype creation in the deserializer as they are not needed in most cases. 9/21/2000 - Simplified the use of the deserializer. No longer need to create the XML object yourself and the load and onLoad methods are part of the Wddx class. 9/30/2000 - Cleaned up code and removed load and onLoad methods. Updated sample code. 12/28/2000 - Added new duplicate method to WddxRecordset object 1/10/2001 - Fixed problem where serialization caused text to always drop to lower case. Thanks to Bill Tremblay for spotting this one! 1/17/2001 - Minor update to the serializer code so that it properly adds text nodes. Thanks for the catch from Carlos Mathews! Also, the deserialization of primitive types now results in primitives rather than instances of the object wrapper 1/20/2001 - Quick fix to the deserializer for recordsets so that for..in loops can get the elements of the recordset in the proper order. 2/5/2001 - Fix to the string deserialization so that it handles special characters properly, thanks to Spike Washburn for this one! 11/9/2001 - Finished small optimizations, fixed encoding issues and fixed case preservation issue. 11/16/01 - (bkruse@macromedia.com)- put all Wddx classes in Object.Wddx namespace to fix scoping issues. 4/19/2002 - Fixed various small bugs with date and number serialization/deserialization 4/19/2002 - Removed Wddx classes from Wddx namespace and put into _global namespace 9/11/2003 - Converted to AS 2.0 by Jobe Makar. Divided into two classes: Wddx and WddxRecordset Authors notes: Serialization: - Create an instance of the Wddx class - Call the serialize method, passing it the object your wish to serialize, it will return an XML object filled with the serialized object. Example: var myXML:XML; var foo:Wddx = new Wddx(); myXML = foo.serialize(bar); Deserializtion: - Get the XML you want to deserialize - Create an instance of the Wddx class - Call the serialize method of your Wddx object and pass it your XML. It will return the deserialized object. Example: var myXML:XML = new XML(); // // XML is loaded here // var foo:Wddx = new Wddx(); var myObj:Object = foo.deserialize(myXML); - Branden 9/30/00 */ class Wddx { // Build some tables needed for CDATA encoding var et:Object = new Object(); var etRev:Object = new Object(); var at:Object = new Object(); var atRev:Object = new Object(); var timezoneString:String; var preserveVarCase:Boolean = true; var useTimezoneInfo:Boolean = true; var packet:XML; var wddxPacket:XMLNode; var useTimeZoneInfo:String; var tzOffset:Number; function Wddx() { for (var i = 0; i<256; ++i) { if (i<32 && i != 9 && i != 10 && i != 13) { var hex = i.toString(16); if (hex.length == 1) { hex = "0"+hex; } et[i] = ""; at[i] = ""; } else if (i<128) { et[i] = chr(i); at[i] = chr(i); } else { et[i] = "&#x"+i.toString(16)+";"; etRev["&#x"+i.toString(16)+";"] = chr(i); at[i] = "&#x"+i.toString(16)+";"; atRev["&#x"+i.toString(16)+";"] = chr(i); } } et[ord("<")] = "<"; et[ord(">")] = ">"; et[ord("&")] = "&"; etRev["<"] = "<"; etRev[">"] = ">"; etRev["&"] = "&"; at[ord("<")] = "<"; at[ord(">")] = ">"; at[ord("&")] = "&"; at[ord("'")] = "'"; at[ord("\"")] = """; atRev["<"] = "<"; atRev[">"] = ">"; atRev["&"] = "&"; atRev["'"] = "'"; atRev["""] = "\""; // Deal with timezone offsets tzOffset = (new Date()).getTimezoneOffset(); if (tzOffset>=0) { timezoneString = "-"; } else { timezoneString = "+"; } timezoneString += Math.floor(Math.abs(tzOffset)/60)+":"+(Math.abs(tzOffset)%60); } // Serialize a Flash object function serialize(rootObj) { delete wddxPacket; var temp:XML = new XML(); packet = new XML(); packet.appendChild(temp.createElement("wddxPacket")); wddxPacket = packet.firstChild; wddxPacket.attributes["version"] = "1.0"; wddxPacket.appendChild(temp.createElement("header")); wddxPacket.appendChild(temp.createElement("data")); if (serializeValue(rootObj, wddxPacket.childNodes[1])) { return packet; } else { return null; } } // Determine the type of a Flash object and serialize it function serializeValue(obj, node) { var bSuccess:Boolean = true; var val:String = obj.valueOf(); var tzString = null; var temp:XML = new XML(); // null object if (obj == null) { node.appendChild(temp.createElement("null")); // string object } else if (typeof (val) == "string") { serializeString(val, node); // numeric objects (number or date) } else if (typeof (val) == "number") { // date object if (typeof (obj.getTimezoneOffset) == "function") { // deal with timezone offset if asked to if (useTimeZoneInfo) { tzString = timezoneString; } node.appendChild(temp.createElement("dateTime")); node.lastChild.appendChild(temp.createTextNode(obj.getFullYear()+"-"+(obj.getMonth()+1)+"-"+obj.getDate()+"T"+obj.getHours()+":"+obj.getMinutes()+":"+obj.getSeconds()+tzString)); // number object } else { node.appendChild((new XML()).createElement("number")); node.lastChild.appendChild((new XML()).createTextNode(val)); } // boolean object } else if (typeof (val) == "boolean") { node.appendChild(temp.createElement("boolean")); node.lastChild.attributes["value"] = val; // actual objects } else if (typeof (obj) == "object") { // if it has a built in serializer, use it if (typeof (obj.wddxSerialize) == "function") { bSuccess = obj.wddxSerialize(this, node); // array object } else if (typeof (obj.join) == "function" && typeof (obj.reverse) == "function") { node.appendChild(temp.createElement("array")); node.lastChild.attributes["length"] = obj.length; for (var i:Number = 0; bSuccess && i1) { dataObj = ""; var i:Number = 0; for (i=0; i=0; i--) { if (node.childNodes[i].nodeName.toLowerCase() == "field") { var attr:Object = this.deserializeAttr(node.childNodes[i].attributes["name"]); dataObj[attr].wddxSerializationType = "field"; for (var j = (node.childNodes[i].childNodes.length-1); j>=0; j--) { dataObj[attr][j] = new Object(); var tempObj:Object = this.deserializeNode(node.childNodes[i].childNodes[j]); dataObj.setField(j, attr, tempObj); } } } // dataObj.wddxSerializationType = "recordset"; return dataObj; } } function deserializeAttr(attr) { var max:Number = attr.length; var i:Number = 0; var char:String; var output:String = ""; while (i