Sorting LowToHigh PHP/XML/Javascript

Vaughan D

This is quite frustrating have been working on it all day.
I am trying to sort The XML document with price from Lowest to highest.
Using PHP.
The XML data is only using the City London, Just for reference
and i did not wish to place the Price in descending order on the XML due to the information i wish to manipulate will not be added statically.

First the codes

var xHRObject = false;

if (window.XMLHttpRequest)
    xHRObject = new XMLHttpRequest();
else if (window.ActiveXObject)
    xHRObject = new ActiveXObject("Microsoft.XMLHTTP");

function retrieveInformation() 
{
    var city = document.getElementById("selectCity").value;
    var type = "";
    var input = document.getElementsByTagName("input");
    for (var i=0; i < input.length; i++)
    { 
        if (input.item(i).checked == true)
            type = input.item(i).value;
    }
      xHRObject.open("GET", "retrieveHotelInfo.php?id=" + Number(new Date) +"&city=" + city + "&type=" + type, true);
      xHRObject.onreadystatechange = function() {
           if (xHRObject.readyState == 4 && xHRObject.status == 200)
               document.getElementById('information').innerHTML = xHRObject.responseText;
      }
      xHRObject.send(); 
}

-

<html>
<head>
<script type="text/javascript" src="retrieveHotelInfo.js"></script> 
</head> 
<body>
Destination:
<br /> 
<select id="selectCity" onchange="retrieveInformation()">
    <option value="London" selected="true">London</option>
    <option value="Paris">Paris</option>
    <option value="New York">New York</option>
    <option value="Chicago">Chicago</option>
    <option value="Seattle">Seattle</option>
</select>
<br />
<br />
Price Range:
<br />
Budget<input name="range" value="Budget" type="radio"  onclick="retrieveInformation()"/>
Standard<input name="range" value="Standard" type="radio" onclick="retrieveInformation()" checked="true"/>
Luxury<input  name="range" value="Luxury" type="radio"  onclick="retrieveInformation()"/>
<div id="information">
</div>
</body>
</html>

-

<?php
 $xmlFile = "hotel.xml";
 $HTML = "";
 $count = 0;
 $dt = simplexml_load_file($xmlFile);
 $dom = DOMDocument::load($xmlFile);
 $hotel = $dom->getElementsByTagName("hotel"); 

 foreach($hotel as $node) 
 { 
 $city = $node->getElementsByTagName("City");
 $city = $city->item(0)->nodeValue;

 $type = $node->getElementsByTagName("Type");
 $type = $type->item(0)->nodeValue;

 $name = $node->getElementsByTagName("Name");
 $name = $name->item(0)->nodeValue;

 $price = $node->getElementsByTagName("Price");
 $price = $price->item(0)->nodeValue;

if (($type == $_GET["type"]) && ($city == $_GET["city"]) )
{
    $HTML = $HTML."<br><span>Hotel: ".$name."</span><br><span>Price: ".$price."</span><br>";
    $count++;
  }
  } 
  if ($count ==0)
 {
  $HTML ="<br><span>No hotels available</span>";
 }

 echo $HTML;   
 ?>

if needed the xml document is written just like this

        <?xml version="1.0"?>
    <hotels>
    <hotel>
        <City>London</City>
        <Name>The Rilton</Name>
        <Type>Luxury</Type>
        <Price>300</Price>
    </hotel>
    <hotel>
        <City>London</City>
        <Name>The Rilton</Name>
        <Type>Budget</Type>
        <Price>150</Price>
    </hotel>
    <hotel>
        <City>London</City>
        <Name>The Rilton</Name>
        <Type>Standard</Type>
        <Price>250</Price>
    </hotel>
    <hotel>
        <City>London</City>
        <Name>The Lolipop</Name>
        <Type>Standard</Type>
        <Price>280</Price>
    </hotel>
    <hotel>
        <City>London</City>
        <Name>The non-Rilton</Name>
        <Type>Standard</Type>
        <Price>225</Price>
    </hotel>
    </hotels>
i alarmed alien

Here's a flexible function that you can use to sort by any criterion. I've also rewritten the XML parsing because you were doing it in a rather inefficient way.

I've used DOMXPath to extract the data from your XML document; it's a useful way of pulling out a set of nodes that match certain criteria without having to iterate through them.

The sort itself is done with usort, which allows you to define a callback for sorting your array items.

# this is the sort function; it takes two arguments, the aspect to sort on, and
# 'asc' or 'desc', depending on whether you want your sort ascending or descending
# the default is ascending

function sort_by( $aspect, $dir ){
    return function ($a, $b) use ($aspect, $dir) {
        if ($a[$aspect] == $b[$aspect]) {
            return 0;
        }
        if ($dir === 'asc') {
            return ($a[$aspect] > $b[$aspect]) ? +1 : -1;
        }
        else {
            return ($a[$aspect] > $b[$aspect]) ? -1 : +1;
        }
    };
}

$dom = new DOMDocument;
$dom->loadXML($xmlFile);

# if you want to search for nodes in an XML document that meet certain criteria,
# there's a handy W3C standard for doing so; it's called XPath, and PHP has an
# interface for it in DOMXPath

$xp = new DOMXPath($dom);
# this is our "base" node
$hnode = $dom->getElementsByTagName("hotels")->item(0);

# get the data that we're searching for from $_GET:
# (you may want to do a little sanitising of these variables first...)
$city = $_GET['city'];
$type = $_GET['type'];

# set up the xpath query to search for hotels with City == $city and Type == $type
# our "base node" is <hotels>, and this query can be translated as "find all the
# direct children of <hotels> that have the tag <hotel> and the children of that
# <hotel> node include <City> with value $city and <Type> with value $type
$results = $xp->query('hotel[ City = $city and Type = $type ]', $hnode);

# check whether we have any results
if ($results->length === 0) {
    echo "<p>No hotels found.</p>\n";
}
else {
# we found hotels!!
    echo "<p>Found " . $results->length . " matching hotels</p>\n";

    # since we are doing the same operation on each XML node, we can condense the code
    # we create an associative array, $hotel, with the hotel properties and the values.
    # that then gets pushed on to an array, $h_data
    $attrs = array('City', 'Type', 'Name', 'Price');
    $h_data = array();
    foreach($results as $h)
    {   $hotel = array();
        foreach ($attrs as $a) {
            $hotel[$a] = $h->getElementsByTagName($a)->item(0)->nodeValue;
        }
        # push the associative array on to $h_data
        $h_data[] = $hotel;
    }

    # Here is the sort criteria. You could get/set this from the page -- e.g.
    # set up $_GET['sort_by'] and $_GET['sort_dir'] if you wanted
    $aspect = 'Price';
    $dir = 'desc'; # or 'desc' for descending

    # check that the aspect is valid -- it should be in the set of $attrs above
    if (! in_array($aspect, $attrs)) {
        $aspect = 'Price';
    }
    # set the search direction to 'asc' unless it is the recognised value 'desc'
    if ($dir !== 'asc' && $dir !== 'desc') {
        $dir = 'asc';
    }

    # pass it to the sorting function...
    usort($h_data, sort_by($aspect, $dir) );

    $html = '';
    # now create our output
    foreach ($h_data as $h) {
        $html .= "<p>" . $h['Name'] ."<br>". $h['Price'] ."<br>". $h['Type'] . "</p>\n";
    }
    echo $html;
}

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related