22 July 2008

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?

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

 

Nice utility,

Thank You

2008-07-25
Chetan Sachdev

Thanks! Saves me from having to write one.

2008-08-14
Justin_P

Cool stuff !

2008-09-01
MajorDOOM

That’s how it should be. Thanks a lot.

2008-09-29
fuX

Thanks!!!!!!!!!!!!!!!!!!!

2008-11-20
Monica H

Perfect… You is a genius! Thanks!

2008-11-28
Jsr

It Works effortlessly.. Great job.

2009-11-30
dineshviswanath

if you replace

for each(var node:XML in list)
{
object = {data:node,order:node[order]};
array.push(object);
}

you can sort by values (“id”) and attributes (”@id”)

2010-03-01
peterP32

Thanks! Very inspiring way to sort. Works a charm when altering it to handle sorting-by-tagName

2010-05-03
Pierre Chamberlain

Thanks for this really good.
Now i want use same in my datagrid as well as tilelist concurrently.if is it possible then plz give me a sample example. how to do.my id:
atulpariharmca@gmail.com

Thanks & Regards
Atul Singh Parihar

2010-06-14
Atul

great! exactly what I need! thanks !

2010-07-07
grigri

To revise peterP32’s post so it will work with the above code:
replace the for each loop with
for each(var node:XML in $xml.children())
{ var object:Object = { data:node, order:node[$attribute] }; xmlArray.push(object);
}

Although one should consider change the name of the function and attribute.

Thanks for the post, awesome stuff.

2010-07-16
Benjamin

Site has been moved

nuff-respec.com is no longer being updated. Please head over to dbulli.com for new content