tags:

views:

863

answers:

2

I am trying to sort an XML list by month, the actual tags have more attributes than just month but for brevity I'll not include them:

<var month="OCT"/>
<var month="NOV"/>
<var month="JAN"/>
<var month="MAR"/>
<var month="SEP"/>
<var month="JUL"/>
<var month="APR"/>
<var month="AUG"/>
<var month="DEC"/>
<var month="FEB"/>
<var month="MAY"/>
<var month="JUN"/>

How can I sort this list in order by month? ...I don't mean alphabetically I mean JAN, FEB, MAR, etc.

Thanks!

+1  A: 

I am not quite clear how you are given the data, but if you HAVE to actually sort the XML, I am guessing you will just have to write a custom sort function.

If you have objects or can parse it into objects, you can use a custom compare function. Here is a function I used to do a case insensitive sort on an array collection of mobile carriers. I also used it to skip sorting the first element in the array collection - CARRIER DEFAULT:

private function x(event:ResultEvent):void{
                for(i=0; i<event.result.carriers.carrier.length; i++){
        _mobile_carriers.addItem({label:event.result.carriers.carrier[i].name, data:event.result.carriers.carrier[i].id});
       }
       var sort:Sort = new Sort();
       sort.fields = [new SortField("label")];
       sort.compareFunction = caseInsensitiveSort;
       _mobile_carriers.sort = sort;
       _mobile_carriers.addItemAt({label:"Mobile Carrier", data:0},0);
       _mobile_carriers.refresh();
}

private function caseInsensitiveSort(obj1:Object, obj2:Object, fields:Array):int{
      if(obj1.label == CARRIER_DEFAULT) return -1;
      if(obj2.label == CARRIER_DEFAULT) return 1;
      return (obj1.label.toLowerCase() < obj2.label.toLowerCase()) ? -1 : 1;
     }

If you have to sort the strings, enumerate the months and then you can just compare them as they will map to integers. There may be a better way to do this, but as a quick solution I might put together a hash:

month_hash=
"JAN" => 1
"FEB" => 2
"MAR" => 3
...

Here is some pseudo code for a compare that can be used in custom compare code, or as a sort function for Sort()

function compare(s1,s2){
   var m1 = ""
   var m2 = ""
   if (s1 =~ /month="([A-Z]+)"/) m1 = $1;
   if (s2 =~ /month="([A-Z]+)"/) m2 = $1;

   if(m1 ==  "" or m2 == ""){ 
     throw exception;
   }else{
      if(month_hash(m1) > month_hash(m2)){
         // string 1's month comes after string 2's month
         // return whatever will indicate that
         return 1;
      }else if(month_hash(m1) < month_hash(m2)){
         // string 1's month comes before string 2's month
         // return whatever will indicate that
         return -1;
      }else{
         //same month
         //return 0
      }
   }

}

No time to post exact code, but hope this helps!

Tony
+1  A: 

I came up with this solution this morning:

function sortXMLListByMonth(xmlList:XMLList):XMLList
{
    var months:Array = ['JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG','SEP','OCT','NOV','DEC'];
    var xml:XML = new XML(<temp></temp>);
    for(var i:uint = 0; i<months.length; i++)
    {
     var tmp:XMLList = xmlList.(@month == months[i]);
     xml.appendChild(tmp);
    }
    return xml.children();
}

It doesn't actually sort the XMLList but returns a sorted copy.

John Isaacks