I wrote a recursive, expanded version that will sort by any number of attributes, in order:
//sort_xml_by_attr($simplexmlobject,array('attr_one','attr_two','attr_three'))
class SortXML {
public $xml;
var $attr;
function SortXML($xml,$attr) {
$this->xml = $xml;
$this->attr = $attr;
}
function cmp_attr($a,$b) {
$a1 = (string)$a->xml[(string)$a->attr];
$b1 = (string)$b->xml[(string)$b->attr];
if (is_numeric($a1) && is_numeric($b1)) {
if (is_float($a1) && is_float($b1)) {
$a1 = (float)$a1;
$b1 = (float)$b1;
} else {
$a1 = (int)$a1;
$b1 = (int)$b1;
}
}
if ($a1 == $b1) return 0;
return ($a1 > $b1) ? +1 : -1;
}
}
function sort_xml_by_attr($xml_obj,$attr) {
if (count($attr)>1) {
// break up array by unique values of the first attribute in the list
$unique_attrs = array();
foreach ($xml_obj as $i) $unique_attrs[] = (string)$i[$attr[0]];
$unique_attrs = array_unique($unique_attrs);
sort($unique_attrs);
// create an array of arrays who share a unique attribute value
foreach ($unique_attrs as $i) {
foreach ($xml_obj as $p) {
if ($p[$attr[0]] == $i) $xml_arrays[$i][] = $p;
}
}
// remove first element to progress the recursion to the next attribute
array_shift($attr);
$new_array = array();
// concatenate sorted arrays
foreach ($xml_arrays as $i) {
$new_array = array_merge($new_array,sort_xml_by_attr($i,$attr));
}
return $new_array;
} else {
// create wrapper objects with new comparison function
foreach ($xml_obj as $i) $new_obj[] = new SortXML($i,$attr[0]);
usort($new_obj,array('SortXML','cmp_attr'));
foreach ($new_obj as $i) $sorted_obj[] = $i->xml;
return $sorted_obj;
}
}