TalkPHP

TalkPHP (http://www.talkphp.com/forums.php)
-   General (http://www.talkphp.com/general/)
-   -   sorting simplexml data by date (http://www.talkphp.com/general/5511-sorting-simplexml-data-date.html)

webosb 07-07-2010 03:04 PM

sorting simplexml data by date
 
Need help with sorting simplexml data by date.

I'm pulling data from an xml feed with simplexml. But the problem is the output doesn't have any kind of ordering. I want to be able to sort them by date. (sort order being from now to future) How would I go about that?

Date value is in this format: 2011-06-17 from $r25->start_date


Here's how my code looks

PHP Code:

$urL "http://www.domain.com/feed.xml";

$ch curl_init();
curl_setopt($chCURLOPT_URL$urL);
curl_setopt ($chCURLOPT_HTTPHEADER, Array("Content-Type: text/xml"));
curl_setopt($chCURLOPT_USERPWD"username:password");
curl_setopt($chCURLOPT_RETURNTRANSFER1);
curl_setopt($chCURLOPT_CONNECTTIMEOUT10);
$output curl_exec($ch);
curl_close($ch);

$feed $output;
$xml = new SimpleXmlElement($feed);
$msg ""

foreach(
$xml->children('http://www.testnet.com/r25') as $entry){
    
$namespaces $entry->getNameSpaces(true);
    
$r25 $entry->children($namespaces['r25']); 
    
$evDate date('F n, Y (l)',strtotime($r25->start_date));
    
$msg .= "<li><span class=\"date\">$evDate</span> - <span class=\"eventTitle\">$r25->event_name</span></li>\n\n";



Salathe 07-07-2010 06:46 PM

There are lots of different ways to do this: here are three ideas.
  1. Use XSL to transform the XML document into one which has the items sorted as you want. This has the advantage of simplicity since your PHP will just see the new, sorted XML and doesn't have to do anything special.
  2. Simply push the elements that you want sorted to an array, then sort that array; perhaps with uasort.
  3. Essentially do the same as #2 but in an object-oriented manner with something like an ArrayObject from the Standard PHP Library.

webosb 07-07-2010 07:40 PM

Doing it with XSL would be great but it's not my xml feed.

I'll look into uasort (never used it before).

Thanks in advance!

Salathe 07-07-2010 09:11 PM

It is not really important that it's not your XML feed, so long as PHP can find, read and load the XML then you can perform some XSL transformation on it (assuming your PHP has XSL enabled).

For example, the following loads the feed for the General forum here and sorts the items in the reverse order that they are presented in the feed. Then it just grabs the title and links.

PHP Code:

<?php

// Load the XML source
$xml = new DOMDocument;
$xml->load(\'http://www.talkphp.com/external.php?type=RSS2&forumids=6\');

$xsl = new DOMDocument;
$xsl->loadXML('<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:template match="channel">
  <talkphp_threads>
   <xsl:for-each select="item">
    <xsl:sort data-type="number" order="descending" select="position()"/>
    <thread>
     <title><xsl:value-of select="title"/></title>
     <href><xsl:value-of select="link"/></href>
    </thread>
   </xsl:for-each>
  </talkphp_threads>
 </xsl:template>
</xsl:stylesheet>'
);

// Configure the transformer
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl); // attach the xsl rules

$sorted $proc->transformToDoc($xml);
$sorted->formatOutput true;
$sorted->preserveWhiteSpace false;
echo 
$sorted->saveXML();

And outputs XML similar to:
Code:

<?xml version="1.0"?>
<talkphp_threads>
  <thread>
    <title>Max Image width and height condition ignored by opera?</title>
    <href>http://www.talkphp.com/general/5440-max-image-width-height-condition-ignored-opera.html</href>
  </thread>
  <thread>
    <title>Setting "submit"</title>
    <href>http://www.talkphp.com/general/5442-setting-submit.html</href>
  </thread>
  <thread>
    <title>include in string ?</title>
    <href>http://www.talkphp.com/general/5454-include-string.html</href>
  </thread>
  <!-- snipped, you get the idea -->
  <thread>
    <title>sorting simplexml data by date</title>
    <href>http://www.talkphp.com/general/5511-sorting-simplexml-data-date.html</href>
  </thread>
</talkphp_threads>


Of course, precisely how the XML is loaded is up to you (e.g. using cURL to provide auth credentials. Also remember that once the new document is available as a DOMDocument (the return value from transformToDoc()) then you can switch over to using SimpleXML if that would make life easier (with the simplexml_import_dom() function)

webosb 07-08-2010 01:46 PM

wow, i never knew XSLT can do this kind of stuff. thanks for showing me an example to learn from. i'll do some more reading on this.

Can you tell me how I would work with namespaces on xsl:for-each?

say if my xml format was like so:

<r25:events ...>
<r25:event>
bunch of stuff here
</r25:event>
</r25:events>

Would it be like:
<xsl:for-each select="/r25:events/r25:event">

??

Salathe 07-08-2010 07:14 PM

As with anything XML-ly, you'll need to make the stylesheet aware of the namespace which you can simply do with something like:

Code:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:dc="http://purl.org/dc/elements/1.1/"
 exclude-result-prefixes="dc">

The highlighted line registers the dc prefix with the http://purl.org/dc/elements/1.1/ namespace. Generally, it is a good idea to keep the namespace prefix the same as that used within the source XML just so you know what matches up with what; however it could equally be xmlns:foobar= even if the XML feed uses the dc prefix for that URI.

Also, the last line (exclude?) simple excludes the namespace from being part of the resulting output from the transformation: it's not required at all, experiment to see how the output is affected with and without it.

As for how to refer to those namespaced elements, you've got the right idea. Use the prefix that you set up in the XSL file.

P.S. Good luck with learning about this topic, it's a pretty huge one (and not one that I even pretend to know a lot about) so take it easy and read lots of material.

webosb 07-09-2010 06:33 PM

Salathe, once again, thanks a million for introducing me to xslt. I played around with the code and got it working. I'm really starting to like XSL now.

If anyone wants to know how I got it to sort, here's what I did (hopefully it helps someone else):

<xsl:sort select="r25:start_date" order="ascending" />

Also, I had to edit the $xml->load line to $xml->load('http://username:password@blah.com/blah.xml');

I tried to use $xml->load($feed); but it returned an error and I also tried $xml->loadxml($feed); but still got an error. I need to figure how I can check the url for errors prior to loading it.


All times are GMT. The time now is 01:17 AM.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.1.0