0

We are fetching data from a remote server via their API. Unfortunately, their API does not order the returned data by date.

I am trying, without much success, to figure out how to re-organize the data so that it is ordered by the next_bookable_date. We are using PHP and SimpleXMLElement to parse the data and create a string which is then inserted into a webpage. But the current result is in the same order as data appears in the returned XML.

The basic XML results are below. There is much more data, that I stripped out to save space.

SimpleXMLElement Object
(
    [request] => GET search.xml?start_date=2013-05-03&end_date=2013-05-17
    [error] => OK
    [total_tour_count] => 4
    [tour] => Array
        (
            [0] => SimpleXMLElement Object
                (
                    [next_bookable_date] => 2013-05-13
                    [tour_name] => Thailand Tour
                )
            [1] => SimpleXMLElement Object
                (
                    [next_bookable_date] => 2013-05-12
                    [tour_name] => Bali Tour
                )
            [2] => SimpleXMLElement Object
                (
                    [next_bookable_date] => 2013-05-05
                    [tour_name] => Hawaii Tour
                )
            [3] => SimpleXMLElement Object
                (
                    [next_bookable_date] => 2013-05-06
                    [tour_name] => Bhutan Tour
        )
    )
)

The PHP code we are using to generate the html string (again stripped of a bit of html code to save space):

foreach($result->tour as $tour) {
$tourname = $tour->tour_name;
$tourdate = $tour->next_bookable_date;

// create string for dpt-soon
$dpt_soon_list .= "<li> some html using the above values </li>\n";
}

Is there a way to re-order the XML data once we receive it from the remote server? Or is there a way to reorder the PHP output when running the foreach?

Tom
  • 2,928
  • 4
  • 28
  • 36
  • 2
    If you're doing purely xml->output, then use simplexml to pull out the relevant data, put it into a standard PHP array, then sort that array with http://php.net/usort Of course, you could also use xslt to do a direct xml->html transform – Marc B Mar 04 '13 at 14:56
  • Related: [PHP sorting issue with simpleXML](http://stackoverflow.com/questions/3023029/php-sorting-issue-with-simplexml); [sort xml div by child node PHP SimpleXML](http://stackoverflow.com/questions/8274193/sort-xml-div-by-child-node-php-simplexml) – hakre Mar 05 '13 at 10:03

1 Answers1

1

You can use usort() to sort multidimensional arrays or objects. I wrote this bit of code to explain how to use it with SimpleXML:

<?php
// Load the XML file
$xml = simplexml_load_file("xml.xml");
// Get all children into an array
$Tours = (array)$xml->children();
$Tours = $Tours["tour"];

// Call usort on the array
usort($Tours, "sorttours");

// Output results
echo "<pre>".print_r($Tours, true)."</pre>";

// The function that specifies when an entry is larger, equal or smaller than another
function sorttours($a, $b) {
    // Parse strings into a date for comparison
    $Date1 = strtotime($a->next_bookable_date);
    $Date2 = strtotime($b->next_bookable_date);

    // If equal, return 0
    if ($Date1 == $Date2) {
        return 0;
    }
    // If Date1 is larger, return 1, otherwise -1
    return ($Date1 > $Date2) ? 1 : -1;
}
?>

This example assumes that the XML looks somewhat like this:

<?xml version="1.0"?>
<tours>
    <tour>
        <next_bookable_date>2013-05-13</next_bookable_date>
        <tour_name>Thailand Tour</tour_name>
    </tour>
    <tour>
        <next_bookable_date>2013-05-12</next_bookable_date>
        <tour_name>Bali Tour</tour_name>
    </tour>
    <tour>
        <next_bookable_date>2013-05-05</next_bookable_date>
        <tour_name>Hawaii Tour</tour_name>
    </tour>
    <tour>
        <next_bookable_date>2013-05-06</next_bookable_date>
        <tour_name>Bhutan Tour</tour_name>
    </tour>
</tours>

If that is not the case, then you need to rewrite the sorttours function to use e.g. attributes to determine the order.

Butt4cak3
  • 2,389
  • 15
  • 15
  • Thanks for pointing me in the right direction. After a bit of trial and error, I got it working. One issue I was running into was the foreach that generated the html string. If the XML contained only one listing, the usort would not create an array and the foreach would go off on an infinite loop. So I had to add an if statement that looked at the tour count and then choose to process it as an simpleXML or go the usort array route. – Tom Mar 04 '13 at 16:37
  • I normally suggest to use `iterator_to_array` instead, see here: http://stackoverflow.com/a/15221083/367456 – hakre Mar 05 '13 at 10:11
  • Thanks @hakre. Didn't know that function until now. In the future I will use iterator_to_array in combination with usort from now on. One never stops learning. – Butt4cak3 Mar 07 '13 at 08:50