TDOT Blog Touchwood Creative

Register | Forgot password?

Author Info

Name
Ben Bishop

Job Title
Senior Interactive Developer



Touchwood is continuing to grow!

We are looking for talented Flex developers to join our Interactive Group. If you have any interest we would love to meet you. Please email your resume to us at:

jobs@touchwoodcreative.com


Actionscript 3: How to use describeType() to Save an Object to XML

Needed Resources:

Final Product:
A base data holder class that will have a toXMLString() method and a parseXML() method to give its descendants the ability to generate a XML string or to instantiate themselves with a XML string.

Execution:

  1. After creating the class file
    and constructor, create the toXMLString method:


public function toXMLString():String{

var x:XML = describeType(this);
var xl:XMLList = x..variable;
var xmlStr:String = "";
xmlStr ="<object type=\""+ getQualifiedClassName(this)
+"\">\r";

for each(var n:XML in xl){

xmlStr += "<variable name=\"" +
n.@name.toString() + "\" type=\"" + n.@type.toString() +
"\">";
xmlStr += this[n.@name.toString()].toString();
xmlStr += "</variable>\r";

}

xmlStr += "</object>";
return xmlStr;

}

This method first starts out by using the describeType utility function
to get a XML object that describes the object. Using e4x, a XMLList is
populated with variable nodes. After creating the root node, the method loops
through the XMLList and creates a series of new variable nodes that have the
actual variable value in addition to data type and variable name.

  1. Next, create the
    "parseXML" method:

public
function parseXML(s:String):void{

try{

var x:XML =
new XML(s);

var xl:XMLList = x..variable;
if(xl.length() == 0){

throw("DataObj
Error: XML does not contain any variable nodes.");

}else{

for each(var
n:XML in xl){

var
varNameStr:String = n.@name;

var varTypeStr:String = n.@type;
var varValueStr:String = n.toString();

if(hasOwnProperty(varNameStr) == true){

try{

this[varNameStr] = varValueStr;


}catch(e:Error){

switch(varTypeStr){

case "Array":

this[varNameStr] =
varValueStr.split(",");

break;

default:

throw("DataObj Error: Conversion of " +
varValueStr + " to " + varTypeStr + " failed for variable "
+ varNameStr + ". \r" + e.message);

break;

}

}

}else{

throw("DataObj Error: XML contains a variable
node that is not a class variable.");

}

}

}

}catch(e:Error){

throw(e.message);

}

}

This method starts off by attempting to parse the
passed string to XML. If there are any problems it throws an exception. Another
exception is thrown if the XMLList of variable nodes doesn't have any elements.
After extracting the variable name, type, and value, the class is tested to see
if it does indeed contain a property of that name. If all is well, the property
is assigned. An exception again will be thrown if there is a problem assigning
the property. In this example, the method does one last check to see if the
variable is an array. If so, appropriate action is taken.

  1. A developer can now extend
    off of this class and declare unique properties while retaining these
    handy methods. For example:

package com.tw.model
{

public class Person extends DataObj
{

public var firstName:String;
public var lastName:String;
public var age:Number;
public var favoriteColors:Array = ["blue", "green",
"red"];

public function Person():void{

}

}

}

In this particular example, the simple data holder
class has been named "DataObj" and extended. A developer can do the
following:

var p:Person = new Person();
p.firstName = "Ben";
p.lastName = "Bishop";
p.age = 27;

When p.toXMLString() is invoked the following is
returned:

<object
type="com.tw.model::Person">

<variable name="lastName"
type="String">Bishop</variable>
<variable name="favoriteColors"
type="Array">blue,green,red</variable>
<variable name="age"
type="Number">27</variable>
<variable name="firstName"
type="String">Ben</variable>

</object>

 

Conversly, a developer can have another class
extend DataObj:

package com.tw.model
{

public class Car extends DataObj
{

//props
public var horsepower:Number;
public var numberOfCylinders:Number;
public var model:String;
public var features:Array;
//constructor
public function Car():void{

}

}

}

This object code be instantiated with the following
code:

var c:Car = new Car();
var xmlStr:String = "<object
type=\"com.tw.model::Car\">";
xmlStr += "<variable name=\"model\"
type=\"String\">";
xmlStr += "Honda Civic";
xmlStr += "</variable>";
xmlStr += "<variable name=\"numberOfCylinders\"
type=\"Number\">";
xmlStr += "4";
xmlStr += "</variable>";
xmlStr += "<variable name=\"features\"
type=\"Array\">";
xmlStr += "power windows, power locks, ABS";
xmlStr += "</variable>";
xmlStr += "</object>";
c.parseXML(xmlStr);

Pretty neat, eh?

What this cold be used for:

  • Saving program states to the
    hard drive via AIR for later retrieval. An example of reading and writing
    XML files can be found here.
  • A quick way to save an object
    to a database through a webservice for later use.
  • A method to save data to an
    AIR SQLLite DB.

Source code for this example can be found attached to this post. Comments
about how to improve and make this more useful is STRONGLY encouraged!

AttachmentSize
Enumerate_Class_Instance.zip254.75 KB

variable == accessor??

It's just me or this example doesn't work if I don't use accessor instead of variable? When I trace my object' describeType(this), I get accessor s instead of variable s

TIA

Careful with bindable properties

You're using
var xl:XMLList = x..variable;

But if the property is bindable, it wont show up because describeType() tags it differntly

eg, if not bindable:

<variable name="myArrayCol" type="mx.collections::ArrayCollection"/>

if bindable:

<accessor name="myArrayCol" access="readwrite" type="mx.collections::ArrayCollection" declaredBy="com.some.package::ClassName">
<metadata name="Bindable">
<arg key="event" value="propertyChange"/>
</metadata>
</accessor>

-ekz

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
© Touchwood Creative 2007 | We use Firefox