Shopping Basket


 x 

Cart empty


Log In

Find Us Elsewhere

SSL

Forum Search

Keyword

If you are a Joomla! developer you are probably already aware that it is possible for the CMS to output many other types of content in addition to the usual html. In fact you can use it to output any type of content that you want, simply by creating a view for it in your component using the appropriate format.

Creating a General XML Feed

In this article I will look at how to use your component to output an XML feed. There is actually more than one approach to this: if you want to create an RSS feed, which is a specific type of XML feed, then you can use the RSS document type - I will discuss this below.

Firstly I will discuss creating a more general type of XML feed, which I will do in the context of a reasonably realistic example. We will suppose that you are developing a Joomla e-commerce component that has a view that displays your products. In addition to the normal HTML output you would like to be able to display an XML feed of the products. It is actually not that hard.

Firstly, in your component views/products folder, alongside the normal view.html.php file, you add another file, called view.xml.php. As you can see, the format of the view is used as an extension immediately before the final .php extension. Then the XML feed would be displayed by supplying the format as an URL parameter, for example using the page link index.php?option=com_example&view=products&format=xml.

So what do you put in the view.xml.php file? A display() method, just as for an HTML document, so it would start off something like this:-

  public function display($tpl = null) { 		
       $app  = JFactory::getApplication(); 		

       $this->state  = $this->get('State'); 		
       $this->items   = $this->get('Data'); //this is the array of data that we are going to display as XML
       $this->params = $app->getParams('com_example'); 		 		
       if (empty($this->items)){
           return;
       }

But instead of displaying HTML output, we are going to output some XML.

Clearing the Output Buffer

Before we do this, we need to clear the Joomla output buffer. The reason why this is a very important thing to do is that the format of an XML document is much stricter than an HTML document, if there is anything already in the output buffer, even a single space, then the output will not be valid XML. This is particularly a problem with Joomla system plugins, because anything that they output goes immediately into the output buffer: even if the developer simply puts a stray space or line-break outside PHP tags, this will go into the buffer, and mess up your XML. So we add this code to our display method:-

	 do{ 			
             //clean all output buffers 		  
         } while(@ob_end_clean()); 

For a similar reason, once we have displayed the output, we will finish with a call to jexit(), to prevent anything manipulating it further (see below). A particular nuisance are system plugins designed to manipulate HTML, but which don't bother to check that the document type is HTML.

Setting the Document Type

Setting the format to 'xml' in the URL parameter is enough to tell Joomla that the document type is XML. That ought to be enough, but unfortunately there is a bug in the Joomla XML document type that results in incorrect content type headers being sent (as text/html), so you will also need to explicitly send the correct content type header as well:-

header ( "Content-Type: application/xml; charset = utf-8", true);

You can use text/xml instead of application/xml, either is acceptable.

Generating the XML

To generate the XML we will use the SimpleXML extension of PHP. It really is simple to use, and is widely supported. To make things a bit easier to follow, we will use a real(-ish) example, and assume that the items array mentioned above consists of an array of products, which we want to use to create a simple product feed, consisting of a product title, description and price for each product (see the illustration). We will start off by creating the root element as a SimpleXML element:-

  $xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><feed></feed>');

Then we add the feed title and store name, assume these are obtained from the view parameters:-

 $title = $this->params->get("title");
 $xml->addChild("title", htmlspecialchars($title));
 $store_name = $this->params->get("store_name");
 $xml->addChild("store", htmlspecialchars($store_name));

Note that we are using htmlspecialchars() to escape the values, this is necessary to prevent parsing errors if the values contain illegal characters (strictly only the < and & characters are illegal in XML, but it doesn't hurt to escape the others too).

Now we create a container for the products data, and then loop through the individual items to add the products.

 $products = $xml->addChild("products");
 foreach($this->items as $item)
 {
   $product = $products->addChild("product");
   $product->addChild("product_title", htmlspecialchars($item->title));
   $product->addChild("product_desc", htmlspecialchars($item->description));
   $product->addChild("product_price", htmlspecialchars($item->price));
 }

Now we have constructed the XML, all that we need to do is echo it as an xml string, then exit.

 echo $xml->asXML();
 jexit();

So the complete display method looks like this:-

  public function display($tpl = null) { 		

       $this->state  = $this->get('State'); 		
       $this->items   = $this->get('Data'); //this is the array of data that we are going to display as XML
       $this->params = $app->getParams('com_example'); 		 		
       if (empty($this->items)){
           return;
       }
       
      do{ 			
       //clean all output buffers 		  
      } while(@ob_end_clean()); 
      
      header ( "Content-Type: application/xml; charset = utf-8", true);
      
      $xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><feed></feed>');
      $title = $this->params->get("title");
      $xml->addChild("title", htmlspecialchars($title));
      $store_name = $this->params->get("store_name");
      $xml->addChild("store", htmlspecialchars($store_name));
      
      $products = $xml->addChild("products");
      foreach($this->items as $item)
      {
         $product = $products->addChild("product");
         $product->addChild("product_title", htmlspecialchars($item->title));
         $product->addChild("product_desc", htmlspecialchars($item->description));
         $product->addChild("product_price", htmlspecialchars($item->price));
      }
  
      echo $xml->asXML();
      jexit();
      
      
   }
         

That's really all there is to it. However we will also take a quick look at the special case of creating an RSS or Atom feed, as it is a special type of XML feed.

Creating an RSS or Atom Feed

This is even simpler, because Joomla includes a feed document type, with a corresponding feed renderer, so you don't actually need to worry about the details of generating the XML, all that you need to do is to supply the items that will be displayed in the feed.

Similarly to the process described above, you create a file called view.feed.php, placed in your views/products folder. Then the feed is accessed using the format and type URL parameters, for example using the page link index.php?option=com_example&view=products&format=feed&type=rss or index.php?option=com_example&view=products&format=feed&type=atom.

The feed document type correctly sets the content type header, so this time we do not need to send the header ourselves.

So in this case the complete code for the display method looks like this:-

public function display($tpl = null) { 		

        $app = JFactory::getApplication();
 	$this->state      = $this->get('State');
 	$this->items = $this->get('Items');
 	$this->params  = $app->getParams('com_example');

 	// Check for errors.
 	if (count($errors = $this->get('Errors')))
 	{
 		throw new Exception(implode("\n", $errors));
 	}
 		
       if (empty($this->items)){
            return;
        }

 	do{ 
			 //clean all output buffers 		   
         } while(@ob_end_clean());
  		  		 
       $document = JFactory::getDocument();
       $type = $app->input->get("type","rss");
       $document->link = JRoute::_('index.php?option=com_example&view=products&format=feed&type='.$type);

       foreach($this->items as $item)
       { 
		$feeditem   = new JFeedItem;
 		$feeditem->title  = $item->title;
 		$feeditem->link  = JRoute::_('index.php?option=com_example&view=product&id='.(int) $item->id);
 		$feeditem->description = $item->description;
 		$feeditem->date  = $item->created_on;

 		$document->addItem($feeditem);
 	}

	echo $document->render();
 	jexit(); 


 }


That's it, it is very easy.