views:

1891

answers:

3

In a Flex webapp, is there an easy way to go about applying a sort to the children of an XML element, based on the children's attributes? Example follows below:

XMLListCollection:

<a anotherProp="ABCDE">
  <e prop="AB">1</element>
  <e prop="BC">2</element>
</a>
<a anotherProp="FGEH">
  <e prop="HF">3</element>
  <e prop="AD">4</element>
  <e prop="AC">5</element>
</a>

I would like to sort the <e> elements, within each <a> element separately, according to their "prop" attribute. My code for generating the array containing the <a> elements is along the lines of:

for each(var node:XML in initialInput:XMLListCollection){
  if(node.localName()=="a"){
    //I was hoping to be able to sort the <e> children of the node variable here
    xmlListCollectionVar.addItem(node);
  }
}

At the end I would like the <a>'s to remain in their defined order, but their <e> children to be sorted based on the "prop" attribute. So far if I try:

node.children().sort=someSortVar

where someSortVar has its fields set to:

SortFields("e.@prop",...)

I get an exception about a null value. Any way to convert the children list to XMLListCollection, sort it and integrate it back into the node variable? Thanks for any replies.

A: 

you can use the sort function on the array with a compareFunction.

... args — The arguments specifying a comparison function and one or more values that determine the behavior of the sort. This method uses the syntax and argument order Array.sort(compareFunction, sortOptions) with the arguments defined as follows:

compareFunction - A comparison function used to determine the sorting order of elements in an array. This argument is optional. A comparison function should take two arguments to compare. Given the elements A and B, the result of compareFunction can have one of the following three values: -1, if A should appear before B in the sorted sequence 0, if A equals B 1, if A should appear after B in the sorted sequence sortOptions - One or more numbers or defined constants, separated by the | (bitwise OR) operator, that change the behavior of the sort from the default. This argument is optional. The following values are acceptable for sortOptions: 1 or Array.CASEINSENSITIVE 2 or Array.DESCENDING 4 or Array.UNIQUESORT 8 or Array.RETURNINDEXEDARRAY 16 or Array.NUMERIC For more information, see the Array.sortOn() method.

Joel Hooks
Sorry - edited title and code - I'm actually using XMLListCollection not an Array. The XML example in my post would be this XMLListCollection (<a><e></e>...</a>).
raptors
A: 

Found suitable code implementations on the Adobe forums - sorry about not looking there first.

http://forums.adobe.com/message/72521#72521

raptors
Another link for a different code implementation is http://forums.adobe.com/message/1950215#1950215
raptors
A: 

I came up with two solutions: The first involved converting an XMLList to an array and sorting on the array:

  for each (var a:XML in elt..a)
  {
    var children:Array = toArray(a.children());
    children.sortOn("@prop");
    a.setChildren(new XMLList());
    for each (var c:XML in children)
    {
      a.appendChild(c);
    }
  }

The second involved using the sort attribute of an XMLListCollection, although I believe that the <a> children are an XMLList, not an XMLListCollection:

  var sort:Sort = new Sort()
  sort.fields = [new SortField("@prop")];
  for each (var a:XML in xml..a)
  {
    var xcoll:XMLListCollection = new XMLListCollection(a.children());
    xcoll.sort = sort;
    xcoll.refresh();
    a.setChildren(xcoll.copy());
  }
Kathy Van Stone
Thank you very much for the solution - the links from the Adobe forums contained solutions along these lines also, but had a bit of overhead in terms of helper functions and whatnot so I think I'll go with your approach involving XMLListCollection.
raptors
I cannot edit your post but you forgot xcol1.refresh(); in the XMLListCollection approach. Just a note to anyone who happens to come across this question in the future.
raptors
I hope I added it at the right place.
Kathy Van Stone
Yup, it's in the correct place.
raptors