Sort XML by Attribute in Actionscript 3

I love working with E4X, but I wish there was an easy way to sort an XML based on an attribute.

After looking around I couldn't really find a good solution or maybe people weren't explaining themselves correctly, or I wasn't googling correctly. So I decided just to write my own small utility class.

When I thought about it. Arrays provide a superb sortOn() function, and it's relatively easy to leverage that.

code

I created a sortXMLByAttribute() public static function in my XMLUtils Class

public static function sortXMLByAttribute  
     (
        $xml       :   XML,
        $attribute :   String,
        $options   :   Object  =   null,
        $copy      :   Boolean =   false
    )
    :XML
 {
    //store in array to sort on
    var xmlArray:Array  = new Array();
    var item:XML;
    for each(item in $xml.children())
    {
        var object:Object = {
            data    : item, 
            order   : item.attribute($attribute)
        };
        xmlArray.push(object);
    }

    //sort using the power of Array.sortOn()
    xmlArray.sortOn('order',$options);

    //create a new XMLList with sorted XML
    var sortedXmlList:XMLList = new XMLList();
    var xmlObject:Object;
    for each(xmlObject in xmlArray )
    {
        sortedXmlList += xmlObject.data;
    }

    if($copy)
    {
        //don't modify original
        return  $xml.copy().setChildren(sortedXmlList);
    }
    else
    {
        //original modified
        return $xml.setChildren(sortedXmlList);
    }
 }

say what?

  • Store XML in an array of objects, where one key is the "order" attribute we want to sort on.
  • Next we just call the Array.sortOn, with whatever options were passed
  • We then loop over sorted array and create a new XMLList
  • We then replace the children of original with sorted children

how to use

$xml : The XML that needs to be sorted
$attribute : The attribute string to sort on
$options : The sorting options, see sortOn()
$copy : If false, original XML is modified.

Here is an example, note this is in a package called XMLUtils

var xml:XML =  
<body id="someId">  
        <p displayOrder="15">Hello</p>
        <p displayOrder="7">World</p>
        <p displayOrder="3">Is</p>
        <p displayOrder="9">This</p>
        <p displayOrder="25">Thing</p>
        <p displayOrder="13">Working</p>
</body>

// original XML object
trace("BEFORE:" + xml);

XMLUtils.sortXMLByAttribute(  
    xml,
    'displayOrder'
);
trace("After:" + xml);

XMLUtils.sortXMLByAttribute(  
    xml,
    'displayOrder', 
    Array.NUMERIC
);
trace("Array.NUMERIC:" + xml");

//multiple options not don't modify orginal
var reverseXML:XML = XMLUtils.sortXMLByAttribute(  
    xml,
    'displayOrder', 
    Array.NUMERIC | Array.DESCENDING, 
    true
);
trace("Array.NUMERIC | Array.DESCENDING:" + reverseXML);  

source
Source code (in package+ + example) xmlutil.zip

Daniel Bulli

I am a yardie (means Jamaican), and develop web type things. Excels at strategy and vision, with a keen sense of design and user interface. An avid photographer, and a frustrated golfer.

Subscribe to Daniel Bulli

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!