Dashboard > Adobe Flex > ... > Integrating Adobe Flex with other technologies > Integrating Flex with XML using XMLConverter
  Adobe Flex Log In | Sign Up   View a printable version of the current page.  
  Integrating Flex with XML using XMLConverter

Added by Daren Klamer , last edited by Daren Klamer on Jan 15, 2008  (view change)
Labels: 
(None)

XMLConverter can be downloaded here

The source code is currently not available, but will be shortly!

Introduction

XMLConverter is an Actionscript library that converts Value Objects to XML, and vice-versa. It uses a combination of reflection, converters, and hints in your code to produce the XML you need for your back-end applications. It was written after having good experiences with XStream, whilst writing Java backends for our Flex applications, and not being able to find a suitable equivalent in Actionscript. You will notice that some concepts from XStream have been used in XMLConverter.

Usage

Using XMLConverter is very simple. Just call toXML() and fromXML() to do the conversion! Below we step through an example of a simple Value Object and how XMLConverter can be used to marshal it to XML and back.

Example

Let's pretend that we're writing an application that will send a customer order to a server, via XML. For now, our Order Value Object only stores simple attributes, as can be seen below:

package net.customware.flex.vo {

    public class Order{
        
        public var id:int;
        
        public var orderDate:Date;
        
        public var subTotal:Number;
        
        public var tax:Number;
        
        public var total:Number;
        
    }
}

Once the application has a populated Order ready to send, all you need to do is tell XMLConverter to convert it.

var order:Order = new Order();
                
order.id = 1234;
order.orderDate = new Date();
order.subTotal = 9.95;
order.tax = 0.99;
order.total = 10.94;

var orderXML:XML = XMLConverter.getInstance().toXML( order );

The resulting XML would then be something like:

<net.customware.flex.vo_Order>
  <orderDate>11/01/2008</orderDate>
  <total>10.94</total>
  <subTotal>9.95</subTotal>
  <id>1234</id>
  <tax>0.99</tax>
</net.customware.flex.vo_Order>

What XMLConverter has done here is use reflection to gather information about the object, and write it accordingly to XML. XMLConverter works with public variables (whether they're bindable or not), Actionscript set/get methods, as well as Java style set/get methods (eg: setId(int id) and getID() ).

You'll notice that the root element of the XML is the fully qualified class name, with some tweaks to make it XML friendly. This can be changed though, by using an alias.

Aliases

Aliases can be used in XMLConverter to replace the class names in the XML with user-friendly names. To register an alias with XMLConverter, simply call the registerAlias method, passing in the class you wish to alias, and the name you want to use.

// register all aliases prior to calling toXML() or fromXML()
    XMLConverter.getInstance().registerAlias("order", Order );

By adding the one line of code to the previous example, the new XML would look like this:

<order>
  <tax>0.99</tax>
  <total>10.94</total>
  <orderDate>11/01/2008</orderDate>
  <id>1234</id>
  <subTotal>9.95</subTotal>
</order>

The order in which the elements are written depends on the Actionscript Reflection API. If you would like to have your XML with the elements in a specific order, you need to have your class implement the XMLElementOrderable interface.

Ordering the elements

XMLConverter has a feature that allows you to tell it which order the properties of your value objects are to be converted to XML. This is done by implementing the XMLElementOrderable interface, which can be seen below:

package net.customware.flex.util.xml.converter {
    public interface XMLElementOrderable {

        function getElementOrder():Array;

    }
}

Here's an example of an implementation, in our Order object:

package net.customware.flex.vo {

    import net.customware.flex.util.xml.converter.XMLElementOrderable;
    import mx.rpc.events.AbstractEvent;
    
    public class Order implements XMLElementOrderable {
        
        public var id:int;
        
        public var orderDate:Date;
        
        public var subTotal:Number;
        
        public var tax:Number;
        
        public var total:Number;
        
        public function getElementOrder(): Array {
            return ["id","orderDate","subTotal","tax","total"];
        }

    }
}

As you can see, we're telling XMLConverter how we want the XML elements to be ordered. By adding the getElementOrder() method to our class, the resulting XML would now look like:

<order>
  <id>1234</id>
  <orderDate>11/01/2008</orderDate>
  <subTotal>9.95</subTotal>
  <tax>0.99</tax>
  <total>10.94</total>
</order>

Now let's assume that we need to make the id an attribute in the XML. The way to tell XMLConverter how to convert a variable to an attribute is to prefix the variable name in the getElementOrder() method with the @ character. Example:

// snip
public function getElementOrder(): Array {
    return ["@id","orderDate","subTotal","tax","total"];
}
// snip

Would result in the XML looking like:

<order id="1234">
  <orderDate>11/01/2008</orderDate>
  <subTotal>9.95</subTotal>
  <tax>0.99</tax>
  <total>10.94</total>
</order>

Converters

You may have noticed that the orderDate attribute has been nicely written to the XML using the DD/MM/YYYY format. XMLConverter knows how to convert specific classes because XMLConverter by default has a DateConverter registered with it. If you have a value object that needs special attention when converting, create a class that implements the Converter interface, and register it with XMLConverter (by using registerConverter(). Also note that the default DateConverter can be overwritten with your own. This handy if the format of your dates is different to the default XMLConverter format. To override the format, simply register the XMLConverter DateConverter, but give it the new format. Example:

XMLConverter.getInstance().registerConverter(Date, new DateConverter("YYYY-MM-DD") );

This will produce the following XML:

<order id="1234">
  <orderDate>2008-01-11</orderDate>
  <subTotal>9.95</subTotal>
  <tax>0.99</tax>
  <total>10.94</total>
</order>

Lists and complex Value Objects

Let's make the Order class a little more descriptive, by adding order lines to it.

//snip Order.as
public var orderLines:ArrayCollection;
//...
public function getElementOrder(): Array {
    return ["@id","orderDate","subTotal","tax","total","orderLines"];
}
//snip
// this has a variety of variable types (Bindable, set / get methods, as well as Java-style setXxx and getXxx methods).
package net.customware.flex.vo {
    import net.customware.flex.util.xml.converter.XMLElementOrderable;
    
    public class OrderLine implements XMLElementOrderable {
        
        public var orderLine:int;
        
        [Bindable]
        public var quantity:int;

        private var _productId:String;
        
        private var _unitPrice:Number;
        
        public function set productId( productId:String ): void {
            _productId = productId;            
        }
        
        public function get productId(): String {
            return _productId;
        }
        
        public function setUnitPrice(unitPrice:Number): void {
            _unitPrice = unitPrice;
        }
        
        public function getUnitPrice(): Number {
            return _unitPrice;
        }
        
        public function getElementOrder(): Array {
            return ["@orderLine","productId","quantity","unitPrice"];
        }
        
    }
}

Now let's populate the order with a couple lines.

var order:Order = new Order();
                
                order.id = 1234;
                order.orderDate = new Date();
                order.subTotal = 9.95;
                order.tax = 0.99;
                order.total = 10.94;
                order.orderLines = new ArrayCollection();
                
                var tempOrderLine:OrderLine = new OrderLine();
                tempOrderLine.orderLine = 1;
                tempOrderLine.productId = "ABC";
                tempOrderLine.quantity = 1;
                tempOrderLine.setUnitPrice(5);
                
                order.orderLines.addItem(tempOrderLine);
                
                
                tempOrderLine = new OrderLine();
                tempOrderLine.orderLine = 2;
                tempOrderLine.productId = "DEF";
                tempOrderLine.quantity = 1;
                tempOrderLine.setUnitPrice(4.95);

                order.orderLines.addItem(tempOrderLine);
                
                
                XMLConverter.getInstance().registerAlias("order", Order );
                XMLConverter.getInstance().registerAlias("orderLine", OrderLine );
                XMLConverter.getInstance().registerConverter(Date, new DateConverter("YYYY-MM-DD") );
                
                var orderXML:XML = XMLConverter.getInstance().toXML( order );

This would produce the following XML:

<order id="1234">
  <orderDate>2008-01-11</orderDate>
  <subTotal>9.95</subTotal>
  <tax>0.99</tax>
  <total>10.94</total>
  <orderLines>
    <orderLine orderLine="1">
      <productId>ABC</productId>
      <quantity>1</quantity>
      <unitPrice>5</unitPrice>
    </orderLine>
    <orderLine orderLine="2">
      <productId>DEF</productId>
      <quantity>1</quantity>
      <unitPrice>4.95</unitPrice>
    </orderLine>
  </orderLines>
</order>
Copyright(c) CustomWare Asia Pacific Pty Ltd
Powered by Atlassian Confluence 2.7.3, the Enterprise Wiki. Bug/feature request - Atlassian news - Contact administrators