2

I have some XML, say:

<Backgrounds>
  <Background>
    <Uses>14</Uses>
  </Background>
  <Background>
    <Uses>19</Uses>
  </Background>
  <Background>
    <Uses>3</Uses>
  </Background>
</Backgrounds>

How can I sort the XML from lowest Uses to highest?

Maybe an xpath expression?

Also, how could I just retrieve the bottom 2 Backgrounds, or the ones most recently added?

hakre
  • 193,403
  • 52
  • 435
  • 836
apple
  • 51
  • 1
  • 2

3 Answers3

4

Examples of sorting with SimpleXML/XPath

How can I sort the XML from lowest Uses to highest?

To sort a list of elements from lowest to highest, you need to create an array of those elements and then sort that array. The xpath expression can be used to obtain both, the array of elements to be sorted as well as the data that array is sorted on (sort-key).

With your XML and the Uses children as sort-value, it works the like the following:

$elements = $xml->xpath('/*/Background');
$sortKeys = $xml->xpath('/*/Background/Uses');

array_multisort($sortKeys, SORT_NUMERIC, SORT_ASC, $elements);

foreach($elements as $i => $element) {
    echo $i, ' ', $element->asXML(), "\n";
}

Which results in:

0 <Background>
    <Uses>14</Uses>
  </Background>
1 <Background>
    <Uses>19</Uses>
  </Background>
2 <Background>
    <Uses>3</Uses>
  </Background>

See array_multisort() and "How do I sort a multidimensional array in php".


Also, how could I just retrieve the bottom 2 Backgrounds, or the ones most recently added?

This is possible to do with xpath alone:

$bottomTwo = $xml->xpath('/*/Background[position() > count(/*/Background) - 2]');

And if most recently added mean the ones on top and not on the bottom:

$topTwo = $xml->xpath('/*/Background[position() < 3]');  
Community
  • 1
  • 1
hakre
  • 193,403
  • 52
  • 435
  • 836
2

Example of sorting with XSLT

XML file:

<employees>

  <employee hireDate="04/23/1999">
    <last>Hill</last>
    <first>Phil</first>
    <salary>100000</salary>
  </employee>

  <employee hireDate="09/01/1998">
    <last>Herbert</last>
    <first>Johnny</first>
    <salary>95000</salary>
  </employee>

  <employee hireDate="08/20/2000">
    <last>Hill</last>
    <first>Graham</first>
    <salary>89000</salary>
  </employee>

</employees>

XSLF file:

<!-- xq424.xsl: converts xq423.xml into xq425.xml -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     version="1.0">

  <xsl:output method="text"/>

  <xsl:template match="employees">
    <xsl:apply-templates>
      <xsl:sort select="salary"/>
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="employee">
    Last:      <xsl:apply-templates select="last"/>
    First:     <xsl:apply-templates select="first"/>
    Salary:    <xsl:apply-templates select="salary"/>
    Hire Date: <xsl:apply-templates select="@hireDate"/>
    <xsl:text>
  </xsl:text>

  </xsl:template>

</xsl:stylesheet>

Source: http://www.xml.com/pub/a/2002/07/03/transform.html

Check predicates here: http://www.w3schools.com/XPath/xpath_syntax.asp for last three nodes.

MartyIX
  • 27,828
  • 29
  • 136
  • 207
1

Possible solution:

  • Parse the XML using SimpleXml
  • Use usort to sort the array containing the background elements.
  • Optionally, export it to XML again (there is no built-in function to do this)

Usort would work as follows:

function comp($a, $b) {
    return $b->Uses - $a->Uses;
}

usort($xml->Backgrounds, 'comp');

Another way is to use an XSLT, with something like this:

<xsl:sort select="Uses"/>
Sjoerd
  • 74,049
  • 16
  • 131
  • 175