Mullanaphy!
Blog
Portfolio
About Me
Contact Me
I'm Mullanaphy!, anything can happen.
Mullanaphy!
Mullanaphy @ bitbucket
Ny newer stuff is on Bitbucket.
Mullanaphy @ github
My older stuff is on Githut.
Final Sandwich
Delivering tasty treats in the form of writings and comics. Enjoy, now!
Jin Hee K.im
She's Korean, so that pretty much guarantees that she's smart, humorous, and cute... mmmmm...
Art of Tom Pollock Jr.
His site might not actually cure AIDS but it might make you ballsy enough to get them and see if it does.
Chris Stein's Artwork
Definitely a good guy to have during an intense brainstorming session. Filled to the brim with mythology, creativity, and a vocabulary. Thats right, vocabulary.
Matt Laskodi
Matt Laskodi is a lot more humorous than you could ever imagine to be... ever... So just deal with it, I know I have.

Blog » PHP's SimpleXMLElement and XML Namespaces. »

2010-11-16: PHP's SimpleXMLElement and XML Namespaces. | 3 Karma ++ --

So decided to use SimpleXMLElement to create simple RSS feeds for Lafango. However there seems to be no easy way to create a simple file like this:

<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
  <channel>
    <title>Lafango - Videos</title>
    <link>http://lafango.com/</link>
    <description>Directory of Videos on Lafango</description>
    <language>en-us</language>
    <pubDate>Tue, 16 Nov 2010 15:29:19 EST</pubDate>
    <lastBuildDate>Tue, 16 Nov 2010 15:29:19 EST</lastBuildDate>
    <managingEditor>support@lafango.com (Admin)</managingEditor>
    <webMaster>webmaster@lafango.com (Admin)</webMaster>
    <ttl>5</ttl>
    <item>
    <link>http://lafango.com/btfffilms/media/12228-pennysavers-trailer</link>
    <pubDate>Tue, 13 Jan 2009 15:29:19 EST</pubDate>
      <title>PennySavers Trailer</title>
    <description>The Theatrical Trailer to this summer's breakout hit...</description>
    <media:title>PennySavers Trailer</media:title>
    <media:description>The Theatrical Trailer to this summer's breakout hit...</media:description>
  </item>
  </channel>
</rss>

Which would think was simple enough to accomplish, yet to get the 'media' namespace was a pain in the tush. With the built in addAttribute('media:title','PennySavers Trailer','http://search.yahoo.com/mrss/'); it was adding the namespace alright, just the problem being it was being added to the nodes themselves and there was no way to just append it to the main RSS node.

So, without adding the namespace to the RSS node as in the example, the readers these were being sent to just laughed at me. That usually means it's time to rummage through php.net's documentation and comments and see if someone else already solved this tiny problem. Unfortunately nothing good came out of it other then having to write my own basic extended SimpleXMLElement. So here it is:

<?php
  class Extended_SimpleXMLElement extends SimpleXMLElement {
    # Source: http://phy.im/m/blog_31/extended_simplexmlelement.php
    
    # Add a namespace to the main node.
    public function addNamespace($namespace=false,$url=false) {
      # Make sure we have a namespace to add.
      if(!$namespace||!$url) return false;
      
      # Add the attribute to the beginning. This will later be
      # stripped out, we just want SimpleXMLElement's auto attribute.

      $this->addAttribute($namespace.':mullanaphy','',$url);
      return $url;
    }
    
    # We need to preg_replace the added $ns:mullanaphy="" out.
    public function asXML() { return preg_replace('# \w+\:mullanaphy=""#','',parent::asXML()); }
    
    # This I actually got from 'Yuri Vecchi' via php.net.
    # liked the idea so added it in. It allows you to chain
    # addAttribute() on the same node.
    # e.g. $node = $XML->addChild('node','')->addAttribute('a',1)->addAttribute('b',2);

    public function addAttribute($name,$value,$namespace=NULL) {
      parent::addAttribute($name,$value,$namespace);
      return $this;
    }
  }

?>

The extension add the addNamespace to the class which allowed me to do what was needed. On top of that added something that seemed pretty cool that was done by a Yuri on php.net's comment section. Lastly asXML needed to be overwritten just for the simple clean up preg_replace.

Here's an example of using the extended class:

<?php
  class Example {
    public function __construct() {
      # Require the class file if you don't have an __autoload() set.
      require_once 'extended_simplexmlelement.php';
      
      # Define the class and provide the default RSS.
      $XML = new Extended_SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"></rss>');
      
      # Add a namespace.
      $media = $XML->addNamespace('media','http://search.yahoo.com/mrss/');
      
      # Add a channel node and fill it up.
      $channel->addChild('title','Lafango - Videos');
      $channel->addChild('link','http://lafango.com/');
      $channel->addChild('description','Directory of Videos on Lafango');
      $channel->addChild('language','en-us');
      $channel->addChild('pubDate',date('D, d M Y H:i:s T');
      $channel->addChild('lastBuildDate',date('D, d M Y H:i:s T'));
      $channel->addChild('managingEditor','support@lafango.com (Admin)');
      $channel->addChild('webMaster','webmaster@lafango.com (Admin)');
      $channel->addChild('ttl',5);
      
      # Iterate through an array and append item nodes.
      foreach($this->fetch() as $row):
        $item = $channel->addChild('item');
        $item->addChild('title',$row->title);
        $item->addChild('link',$row->url);
        $item->addChild('description',$row->description);
        $item->addChild('media:title',$row->title,$media);
        $item->addChild('media:description',$row->description,$media);
      endforeach;
      echo $XML->asXML();
    }
    
    private function fetch() { /* gets some array data from someplace, don't worry about it. */ }
  }

  
  new Example;
?>

Granted in this example we could have easily included the namespace inside the rss node during the __construct(), however in my situation the RSS attributes needed to be dynamic as RSS was defined on an abstract class and those extending it all had different needs.

This solution is probably not that relevant yet if it saves someone time then so be it. Please use and abuse this freely.

Comments »

Posted by Cherrymi at 2010-11-26

Hi, John! Don't know if u still remmember me, haha. We were penpals about two years ago. Good to see that u r still updating ur blog. I'm now studying in the US. Just want to say hi and wish u and ur family a happy Thanksgiving!

Email . Website

Posted by Mullanaphy! at 2010-11-21

Too add, someone could get crafty with the addNamespace. Store locally inside the class the namespace, something like:
$this->namespaces[$name] = $url;

Then rewrite addChild to preg_match the child name for "#(\w+):\w+#". Then if isset($this->namespaces[$matches[1]]) to auto append $this->namespace[$matches[1]] as the namespace on the outside. So in essence, addChild doesn't need the third parameter if you've already used addNamespace();

Think I'll update the linked Extended_SimpleXMLElement to accommodate that.

Name
Email
Website
Comment
Note, any comment possessing HTML is stripped, any message possessing a website won't even be posted, nor will any message that is just one word.