Sort any XML file in PHP with this XSL

No Gravatar

XMLI was working on a project a while back that required a web interface to edit, delete, and insert event entries into an XML file. My biggest problem was that anytime I would edit or insert an event element, it would appear in the XML file as the last node rather than in date order. I figured out how to sort the XML contents as they were rendered in HTML using an XSLT (EXtensible Stylesheet Language Transformation). This worked fine for that particular display but this XML needed to be displayed several different ways in different places and I wasn’t thrilled with the thought of having to create an XSL file for every variation. All I really needed was one XSL file to sort the XML data each time it was updated.

There is a dearth of good documentation with examples on just how to do this. I spent hours running Google searches and browsing forums gaining a small bit of relevant info each time, but never enough for the whole picture. Most of this had to be figured out through good old fashioned trial and error. And there were a LOT of errors. Quite often I would destroy the entire XML file and would have to copy it again from backup. I felt quite jubilant when I finally created an XSL that would take my unsorted XML file and return the sorted one. But being the glutton for punishment that I am, I decided I didn’t want to stop there. I knew you could pass variables to XSL files so why couldn’t I create an XSL file that could sort any XML file I pass to it on whatever field I wanted?

This turned out to be much more difficult than I could have ever imagined. I had to find a way to remove everything in my XSL that was specific to my event XML date sort and pass a variable for it instead. Turns out there are many element attributes in XSL that refuse to use a variable or require special formatting for their variables. Anyhow, after a lot of trial and error, I finally sorted it all out. First I’m going to show a generic bit of XML to use as an example, then show the XSL file, and then the PHP function I used to perform the sort. Here’s a pretty simple XML sample document called events.xml:



	
		Easter
		20100404
	
	
		Christmas
		20101225
	
	
		Halloween
		20101031
	

And here is the magical XSL document called sortxml.xsl:





  
    
  


  
     
     
       
     
  


And finally, here is the PHP function which makes it all happen:

function sortxml( $xmlfile, $sortby, $type = 'number', $order = 'ascending', $child ) {
	// $type: number|text|qname
	// $order: ascending|descending
	$xp = new XSLTProcessor();
	$xsl = new DomDocument;
	$xsl->load('sortxml.xsl');
	$xp->importStylesheet($xsl);
	$xml_doc = new DomDocument;
	$xml_doc->load($xmlfile);
	$xp->setParameter('', 'sortby', $sortby);
	$xp->setParameter('', 'type', $type);
	$xp->setParameter('', 'order', $order);
	$xp->setParameter('', 'child', $child);
	$sorted = $xp->transformToXML($xml_doc);
	$fh = fopen($xmlfile, 'w') or die("can't open file");
	fwrite($fh, $sorted);
	fclose($fh);
}

To sort an XML file, just call the sortxml() function with the arguments you need to get the desired result. For example, to sort my events.xml chronologically (ascending) by date I would call the function as follows:

sortxml('events.xml', 'date', 'number', 'ascending', 'event' );

The first argument is the location of the XML file. The second specifies the node containing the value to be sorted on. The third establishes the data-type (text or number) of that value. The fourth sets the sort-order (ascending or descending). The last identifies which nodes are to be sorted. After calling my sortxml() function, my events.xml file now looks like this:



	
		Easter
		20100404
	
	
		Halloween
		20101031
	
	
		Christmas
		20101225
	

If I wanted to sort the file alphabetically by event name, I would call the function this way:

sortxml('events.xml', 'name', 'text', 'ascending', 'event' );

And my events.xml file would then look like this:



	
		Christmas
		20101225
	
	
		Easter
		20100404
	
	
		Halloween
		20101031
	

And there you have it. I haven’t tested this on many other XML files so I can’t guarantee it will work for you like it does for me. If you have any questions, feel free to comment below. Cheers.

 

5 Responses to “Sort any XML file in PHP with this XSL”

  • James Holmes

    Hi Chuck,

    thanks for this script! It’s something that I looked for. But I have to say, that it gave me error while loading XSL file. The error was “Premature end of data in tag stylesheet line 2 in Entity”.

    It’s because of missing ending “/”, for example here: . It should be: .
    The same situation is on the line 11 and 13.

    After these corrections everything works OK! So once again, thank you.

    Regards,
    James

  • Ed

    Hello Chuck,

    I’m quite excited to have come across your xml sorting codes so early in my attempts to learn php and xsl and xml.

    Unfortunately, I’m not having any success using them. At this time, nothing happens when I click on buttons to run your php sortxml function.

    Do you know if it matters if I swapped all encoding to UTF-8; I also tried Unicode?

    If you are feeling extra generous please feel free to check out the analogous files I copy-pasta’d and lemme know if something jumps out at you:

    http://www.claritytutors.com/test.php
    http://www.claritytutors.com/sortxmltest.xsl
    http://www.claritytutors.com/test_holidays.xml

    Thanks for posting,
    Ed

  • Hi chuck:

    I have been looking for this example for a long time but it doen’t seem to work.

    Do you know why?

    Thank you!

    Daniel.

  • [...] a look into this .post_btns {margin-top: 10px;} .btns_left {float:left;} .btns_right {float:right;} Share [...]

  • Phil Templeton

    @Daniel, you might want to check to see if the tags are capitalized when you pasted the code into your document. I got stuck on that, otherwise code works great. Thanks Chuck!

Leave a Reply