Sorting an array of SimpleXML objects

I read what I found in Stackoverflow, and is still unclear.

I have an array of SimpleXML objects like this:

array(2) { [0]=> object(SimpleXMLElement)#2 (2) { ["name"]=> string(15) "Andrew" ["age"]=> string(2) "21" } [1]=> object(SimpleXMLElement)#3 (2) { ["name"]=> string(12) "Beth" ["age"]=> string(2) "56" } } 

And I want to be able to sort by any column, ascending or descending. Something like:

 sort($data, 'name', 'asc'); 

Where can I go in the array of objects above and sort by the value of what I like.

For reference, a similar .NET solution would be as follows:

 XmlSortOrder order = XmlSortOrder.Ascending; if ( sortDirection == "asc" ) { order = XmlSortOrder.Ascending; } expression.AddSort( columnSortingOn + "/text()", order, XmlCaseOrder.UpperFirst, "en-us", XmlDataType.Text ); 

I saw people say

"Use usort"

The following is a basic example from a PHP manual, but that doesn't really explain it. At least not for me. I also saw that people suggest using an external library such as SimpleDOM, but I want to avoid using something external for this (it would seem, although I still can not solve it).

Any help is appreciated, thanks!

+7
sorting php simplexml
source share
6 answers

I assume that people suggesting using SimpleDOM will be me. :)

I wrote SimpleDOM :: sort () just for this situation, because to sort SimpleXMLElements using an arbitration expression (or arbitrary expressions) you need to use array_multisort() , which is boring and will not teach you anything useful.

Here is a short version of how this works: first you create a proxy array from the key => value pairs corresponding to each SimpleXMLElement element and the value with which they will be sorted. In your example, if you want to sort them by <age/> , the array will be array(21, 56) . Then you call array_multisort() with a β€œproxy array” as the first argument, followed by any number of sorting modifiers , such as SORT_DESC or SORT_NUMERIC, and then finally the array you want to sort, which will be passed by reference.

You end up with something like this:

 $nodes = array( new SimpleXMLElement('<person><name>Andrew</name><age>21</age></person>'), new SimpleXMLElement('<person><name>Beth</name><age>56</age></person>') ); function xsort(&$nodes, $child_name, $order = SORT_ASC) { $sort_proxy = array(); foreach ($nodes as $k => $node) { $sort_proxy[$k] = (string) $node->$child_name; } array_multisort($sort_proxy, $order, $nodes); } xsort($nodes, 'name', SORT_ASC); print_r($nodes); xsort($nodes, 'age', SORT_DESC); print_r($nodes); 

But in fact, instead of burdening yourself with a lot of code, you have to maintain and possibly rewrite array_multisort() in user space, you should use existing solutions. There is nothing interesting in such a sorting algorithm / subroutine; it’s better to spend your time on something that does not exist yet.

+3
source share

The usort function lets you tell PHP

Hey, you! Sorting this array I give you this function that I wrote.

It has nothing to do with SimpleXML. This is a universal function for sorting a collection of PHP built-in arrays.

To sort an array, you need to write a function, an instance method, or a static method. The second usort argument accepts PHP Callback , which is a pseudo-type that allows you to specify which function, instance method, or static method.

The function you are writing will take two arguments. These will be two different values ​​from your array.

 function cmp($a, $b) { if ($a == $b) { return 0; } if($a < $b) { return -1; } if($a > $b) { return 1; } } 

You need to write this function to return one of three values.

 If $a == $b, return 0 If $a > $b, return -1 if $a > $v, return 1 

When you call usort, PHP will run through your array, calling the sort function / method (in this case, cmp again and again until the array is sorted. In your example, $ a and $ b will be SimpleXML objects.

+4
source share

I was ready to recommend usort() until I realized that you had already beaten me. Since the code examples in the past did not bring much benefit, I will try to just explain it in plain English and hopefully it will force you to point in the right direction.

Using usort() , you create your own custom algorithm created by the user. The usort() function calls your own comparison function to determine how each of your objects is related to each other. When writing your comparison function, you will get two objects inside your array. With these two objects, you return a result that essentially tells usort() whether the first object is LESS THAN , EQUAL TO or GREATER THAN second object. You do this by returning -1, 0, or 1 (respectively). It. You only need to take care of how the two objects are compared with each other, and the actual sorting mechanics are handled by usort() for you.

Ok, now for a semi-practical example:

 function myCompare($obj1, $obj2) { if($obj1->someInt == $obj2->someInt) { return 0; // equal to } else if($obj1->someInt < $obj2->someInt) { return -1; // less than } else { return 1; // greater than } } $myArray = {a collection of your objects}; usort($myArray, 'myCompare'); 

This is pretty much an example in PHP Manual, but hopefully it makes sense in context now. Let me know if I don’t understand something.

+2
source share

The Josh Davis solution does not seem to work when loading the XML file via:

 $nodes = simplexml_load_file('/home/usr/public_html/feeds/deadlines.php'); 

I get the following error:

Warning: array_multisort() [function.array-multisort]: Argument #3 is expected to be an array or a sort flag in /home/usr/public_html/feeds/deadlines.php on line 8

It refers to: array_multisort ($ sort_proxy, $ order, $ nodes);

+2
source share

Here is another example of using usort() . This allows you to specify the object variable and sort direction:

 function sort_obj_arr(& $arr, $sort_field, $sort_direction) { $sort_func = function($obj_1, $obj_2) use ($sort_field, $sort_direction) { if ($sort_direction == SORT_ASC) { return strnatcasecmp($obj_1->$sort_field, $obj_2->$sort_field); } else { return strnatcasecmp($obj_2->$sort_field, $obj_1->$sort_field); } }; usort($arr, $sort_func); } 

Test code;

 class TestClass { public $name; public $age; public function __construct($name, $age) { $this->name = $name; $this->age = $age; } } $test[] = new TestClass('Tom', 28); $test[] = new TestClass('Mary', 48); $test[] = new TestClass('Beth', 38); $test[] = new TestClass('Cindy', 18); $test[] = new TestClass('Sid', 58); $test[] = new TestClass('Mandy', 8); $field = 'age'; $direction = SORT_DESC; sort_obj_arr($test, $field, $direction); echo '<pre>'; print_r($test); echo '</pre>'; 
+1
source share

this is an old thread, but here is my solution that is used to extract information from an RSS feed for sorting by title

 $xml = simplexml_load_file('rss.xml'); $msg = array(); $msg_count = $xml->channel->item->count(); for ($x=0;$x<$msg_count;$x++){ $msg[$x]['titl'] = (string)$xml->channel->item[$x]->title; $msg[$x]['link'] = (string)$xml->channel->item[$x]->link; $msg[$x]['date'] = (string)$xml->channel->item[$x]->pubDate; $msg[$x]['time'] = strtotime(substr((string)$xml->channel->item[$x]->pubDate,4)); $msg[$x]['desc'] = (string)$xml->channel->item[$x]->description; $msg[$x]['auth'] = (string)$xml->channel->item[$x]->author; } foreach ($msg as $key => $row) { $titl[$key] = $row['titl']; $link[$key] = $row['link']; $pdat[$key] = $row['date']; $time[$key] = $row['time']; $cate[$key] = $row['cate']; $desc[$key] = $row['desc']; $auth[$key] = $row['auth']; } array_multisort( //change $titl to any variable created by "foreach" $titl, SORT_ASC,SORT_NATURAL | SORT_FLAG_CASE, $msg); 
+1
source share

All Articles