SimpleXML

One thing I have found is the lack of really simple XML classes—that’s not to say there aren’t any good ones out there, I have used several really cracking ones. For my new version of my personal site (yes, this site is planned for a revamp) I wanted to integrate my Twitter feed somewhere. I looked and looked for a really simple XML class but was unable to find one. So I made one. And here is the result:

The code

  1. <?php
  2. /**
  3.  * @author Christopher Hill
  4.  * @copyright (c) Christopher Hill
  5.  * @package chrisjhill
  6.  * @version 0.2
  7.  */
  8. class myXmlParser
  9. {
  10.    /**
  11.     * The URL to the XML source
  12.     * @access private
  13.     * @var string
  14.     */
  15.    private $_url;
  16.  
  17.    /**
  18.     * Whether or not to add this value
  19.     * @access private
  20.     * @var boolean
  21.     */
  22.    private $_ignore false;
  23.  
  24.    /**
  25.     * The attributes to allow to be added
  26.     * @access private
  27.     * @var array
  28.     */
  29.    private $_want = array();
  30.  
  31.    /**
  32.     * The XML Parser class
  33.     * @access private
  34.     * @var object
  35.     */
  36.    private $_xml_parser;
  37.  
  38.    /**
  39.     * The result set of the parsing
  40.     * @access private
  41.     * @var array
  42.     */
  43.    private $_return = array();
  44.  
  45.    /**
  46.     * The class constructor
  47.     * @access public
  48.     */
  49.    public function __construct($url) {
  50.       $this->_url $url;
  51.       $this->_xml_parser xml_parser_create();
  52.       xml_set_element_handler($this->_xml_parser,
  53.          array($this'startTag'),
  54.          array($this'endTag'));
  55.       xml_set_character_data_handler($this->_xml_parser,
  56.          array($this'contents'));
  57.    }
  58.  
  59.    /**
  60.     * Set a wanted attribute
  61.     * @access public
  62.     * @param mixed $want
  63.     */ 
  64.    public function setWant($want) {
  65.       if (is_array($want)) {
  66.          foreach ($want as $value) {
  67.             $this->_want[] = $value;
  68.          }
  69.       }
  70.       else {
  71.          $this->_want[] = $want;
  72.       }
  73.       return $this;
  74.    }
  75.  
  76.    /**
  77.     * Set the ignore
  78.     * @access private
  79.     * @param boolean $ignore
  80.     */
  81.    private function setIgnore($ignore) {
  82.       $this->_ignore = (bool)$ignore;
  83.       return $this;
  84.    }
  85.  
  86.    /**
  87.     * Returns the ignore variable
  88.     * @access private
  89.     * @return boolean
  90.     */
  91.    private function getIgnore() {
  92.       return $this->_ignore;
  93.    }
  94.  
  95.    /**
  96.     * Return the want array
  97.     * @access private
  98.     * @return array
  99.     */
  100.    private function getWant() {
  101.       return (array)$this->_want;
  102.    }
  103.  
  104.    /**
  105.     * Parses the XML input
  106.     * @access public
  107.     */
  108.    public function parse() {
  109.       $fp fopen($this->_url"r"); 
  110.       $data fread($fp80000);
  111.  
  112.       if(!(xml_parse($this->_xml_parser$datafeof($fp)))){ 
  113.           die("Error on line " xml_get_current_line_number($this->_xml_parser)); 
  114.       }
  115.    }
  116.  
  117.    /**
  118.     * Set whether to output this attribute
  119.     * @access private
  120.     * @param object $parser
  121.     * @param string $data
  122.     */
  123.    private function startTag($parser$data){ 
  124.       $this->_ignore in_array(strtolower($data), $this->getWant())
  125.           ? true
  126.           false;
  127.    } 
  128.  
  129.    /**
  130.     * This function does nothing, but is needed to stop parse errors
  131.     * @access private
  132.     * @param object $parser
  133.     * @param string $data
  134.     */
  135.    private function endTag($parser$data){ 
  136.       // Do nothing
  137.    }
  138.  
  139.    /**
  140.     * Echo out the contents of the atttribute
  141.     * @access private
  142.     * @param object $parser
  143.     * @param string $data
  144.     */
  145.    private function contents($parser$data){ 
  146.       $data trim($data);
  147.       if ($this->_ignore && !empty($data)) {
  148.          if (count($this->_return[(count($this->_return) - 1)]) == count($this->_want)) {
  149.             $this->_return[count($this->_return)][] = $data;
  150.          }
  151.          else {
  152.             $this->_return[(count($this->_return) == count($this->_return) - 1)][] = $data;
  153.          }
  154.       }
  155.    }
  156.  
  157.    /**
  158.     * Return the output array
  159.     * @access public
  160.     * @return array
  161.     */
  162.    public function getReturnArray() {
  163.       return $this->_return;
  164.    }
  165. }

And you use it like this

  1. <?php
  2. $myXmlParser = new myXmlParser('http://twitter.com/statuses/user_timeline/chrisjhill.xml');
  3. $myXmlParser->setWant(array('text''created_at'))->parse();
  4. echo '<pre>';
  5.    print_r($myXmlParser->getReturnArray());
  6. echo '</pre>';

Which will produce the following result:

  1. Array
  2. (
  3.     [0] => Array
  4.         (
  5.             [0] => Tue Mar 25 16:24:41 +0000 2008
  6.             [1] => Just got back from a challenging run, don't feel too tired though...
  7.         )
  8.  
  9.     [1] => Array
  10.         (
  11.             [0] => Mon Feb 25 18:14:21 +0000 2008
  12.             [1] => I'm fixing my XML parser class. It's better than I remember, I might consider posting it on my blog!
  13.         )
  14.  
  15.     [2] => Array
  16.         (
  17.             [0] => Sat Jan 19 21:44:14 +0000 2008
  18.             [1] => I cannot believe it. My se7ev DVD has had its end corrupted. 1 hour 40 of my life wasted...
  19.         )
  20.  
  21. )

Now thats some nice output

I love working with arrays, the more complex they are the better. This one is quite simple though, it adds each feed into a array index which has 2 children; the date posted and the content. Simple.

A little information on using it

The class works by first supplying a URL to the XML source in the constructor. You then set what fields you want to save, and discard the rest. This saves memory without having to store data you will not use. Call the parse() function and it will work its magic. And yes, the class can make use of method chaining. Enjoy.


Related articles

Top | Post a comment | Permalink

User submitted comments

1 Paul wrote

23rd April, 2008


Hi Chris, a nice compact class that does what it says on the tin. I’m interested that you say you couldn’t find any good xml classes. For a Twitter feed try the Zend_Feed class. Its standalone and doesn’t require you to use the frame work. It works simply with the following code:

  1. <?php
  2. try {
  3.     $slashdotRss Zend_Feed::import('http://rss.slashdot.org/Slashdot/slashdot');
  4. } catch (Zend_Feed_Exception $e) {
  5.     // feed import failed
  6.     echo "Exception caught importing feed: {$e->getMessage()}\n";
  7.     exit;
  8. }
  9. $slashdotRss // an array with all required information

2 Christopher Hill wrote

23rd April, 2008


Very nice, good spot Paul! I haven’t looked into the Zend Framework yet but it is right at the top of my todo list—it seems to support white lists which is one of my key functional requirements.


Penny for your thoughts

Comment posting guide

Your real name will be displayed as the author of the post. Real names are preferred, both first and second names, but nicknames/alter-egos are permitted. Any comments with the author name whose primary aim is to promote their website, and/or company will be removed.

If you supply a website URI then your real name will be clickable to that site. Only one sub-directory is permitted; e.g. http://www.example.org/directory.

Accepted comment input

  • <strong>…</strong>
  • <em>…</em>
  • <blockquote>…</blockquote>
  • <tt>…</tt>
  • <a href="…">…</a>
  • <code>…</code>




Recent articles

Other topics I ramble on about