Thursday, August 14, 2008

PHP and XSL Part 3

This is the third entry in a three part series on the advantages of using XML and XSL to generate a web page. Part one will focus on the downsides of echoing HTML through PHP and how an XML/XSL driven system overcomes these shortcomings. Part two will focus on how PHP uses DOMDocument and the XSLTProcessor to generate XML documents and convert the XML into XHTML with an XSL stylesheet. Part three will introduce the DOMi object, a purpose built class that is designed to simplify and speed up the process of building XSL driven websites.

Part 3 - Introducing DOMi

In Part 1 and Part 2 of this article, I explained why the traditional method of HTML echo is on the brink of obsolescence, and why the DOMDocument object is the next logical step in web development. However, if you have used DOMDocument and XSLTProcessor before, you know one major downfall to using those systems - monotonous, tedious tasks to build even a simple object, followed by a hard to remember series of commands to render the XML through the XSLTProcessor.

In Part 3, I will introduce an open source tool that is my bread and butter for XSL driven websites - the DOMi object. DOMi was created purely for XSL driven websites, and as such houses several very useful tools for speeding up the process and briding the gap between PHP data structures, such as arrays, and an XML tree.

How is DOMi used?

DOMi is used in the same way that DOMDocument is used. An instance is created and manipulated. Infact, DOMi has every single function that DOMDocument has. DOMi contains a DOMDocument, XSLTProcessor and DOMXpath, transparently accessed through DOMi. In essence, the following two lines of code are the same...

$Domi->createElement('element');
$Domi->Dom->createElement('element');


The first line attempts to invoke createElement as though it were a member method of $Domi, whereas the second line accesses the $Domi->Dom member property, which is a DOMDocument, and invokes its createElement method. Domi transparently passed the parameters to the DOMDocument object, and will even return it's results. This means that anything written for DOMDocument can be transferred to DOMi with absolutely no issues.

How does DOMi make it easier to build an XML tree?

PHP wasn't designed to manipulate the DOMDocument. It was designed to manipulate arrays and strings and integers. So when you try to use DOMDocument's createElement, appendChild and setAttribute methods to build an XML tree, you will quickly find the process to be extremely time consuming. Building even a simple tree is a labor of many lines and more time than should be required to simply convert one data structure into another.

Enter DOMi::AttachToXml - a method that receives a large variety of data types and converts them to XML and attaches them to the DOMDocument stored within DOMi. AttachToXml accepts two parameters, a data structure and a prefix. The prefix determines what to name the node that is being built, and the data structure is then built into that node, and the node is attached to the root of the DOMDocument. In addition, if you don't want the node attached at the base, you can pass a third, optional parameter that is a DOMNode within the DOMDocument, and the data will be attached as a child node to that DOMNode.

With this system, you can pass an infinitely large multidimensional array to AttachToXml and have a perfect XML tree, ready for the XSLTProcessor. Also - by naming keys in certain fashion, you can even set up your attributes just as easily. With this system, a proper database abstraction layer and a well set up database, you can convert a store's database into an XML tree ready for display in less than 5 lines of code.

How does DOMi render pages?

When DOMi was built for XSL driven websites, there was an obvious need for rendering support. The DOMi::Render method is designed to display a page in one of three formats - HTML, XML or View. The HTML output is the final rendered output, combining the XML and XSL into a web page. The XML output is used for debugging mode to see what the current DOMDocument XML tree looks like - which is essential when you are designing your XSL stylesheets. The View output is a system to convert from one DOMDocument into another and display it on screen as XML. It is used similar to a database view, in that it allows you to alter the real storage structure, and so long as the view is properly updated, any external calls to the XML will still work. This is a great tool for building an API.

To render a page with DOMi, you must first import a stylesheet through the XSLTProcessor::importStylesheet() method. Due to the transparent nature of DOMi, this method can be invoked as DOMi::importStylesheet(). Just as with a regular XSL driven system, importStylesheet requires to be given a DOMDocument that contains an XSL stylesheet, but DOMi has provided tools for importing those stylesheets easily. DOMi::GenerateXSL() receives an array that contains file locations of XSL stylesheets and returns a DOMDocument of an XSL stylesheet that includes all provided stylesheets. This allows for dynamic inclusion of XSL stylesheets, which is useful for CMS skinning.

The stylesheet that is returned by DOMi::GenerateXSL can then be provided to DOMi::importStylesheet and used for final rendering. The last task is to render the page using DOMi::Render(), which accepts one parameter, which is either DOMi::RENDER_XML, DOMi::RENDER_HTML, or DOMi::RENDER_VIEW, and based on what is sent, the DOMi will render the desired results.

A brief look at DOMi

An example of DOMi code to get a list of employees and render on screen is shown below. This script assumes you already have a stylesheet and a function that returns an array of employee data.

//create the document with the root node as 'root'
$Domi = new DOMi('root');

$Domi->AttachToXml(GetEmployeeList(), 'employee')); //attach the array to the DOMDocument

$Domi->importStylesheet($Domi->GenerateXSL(array('stylesheet.xsl')));

$Domi->Render(DOMi::RENDER_HTML);


Conclusion

HTML echo is an old system that needs to be put to pasture. Its limitations are now too great to consider it a viable system for much longer, and a better system has been established. Why continue writing sites in a system that fails in so many regards? Upgrade to an XSL based system as soon as possible. After you get used to it, you'll begin viewing HTML echo in the same light you now view table based designs (I hope, if not, I highly recommend looking into CSS based designs). XSL has a bit of a hard barrier to break. Initially, it seems backwards and worse than HTML echo, but as you get more skilled with it, you begin to realize it's strength, and once you are as skilled with XSL as you are with HTML echo, it becomes painfully clear that HTML echo is a dying system, or at the very least, will be a dying system in the near future.

Sourceforge.net - DOMi

1 comment:

I Am Zippy said...

Hi Steve
This is a nice set of articles. I totally agree with your position on HTML as a legacy we need to forget.

The power of XPath is awesome indeed, being capable of querying along any axis with the selectivity of predicates, and can even turn corners during the search. Yes, it was a steep curve at the beginning (I'm an XSL freak for like 8 years) but the pay-off is immense.

I just d'l-d DOMi to give it the once-over. As you know, there's not a great deal of user input or even documentation right now, but this is a methodology whose time has come.

I'll get back when I know more.