Using XSLT And PHP to Generate Output in Different Formats
Using PHP to perform XSLT can degrade performance on a web site quite substantially. It's preferable, instead, to use transformation simply as a one-time publishing mechanism to generate static HTML or XML files on the server, which can be parsed and returned to the client faster than code-intensive PHP scripts. Yes, you need to regenerate, or republish, the static documents each time your stylesheet or XML source changes, but the extra effort pays dividends in terms of better web server performance and faster response times.
With this in mind, this example demonstrates an extremely primitive publishing system. I use a single XML document and multiple XSLT stylesheets to output data in three different formats: HTML, WML, and comma-separated ASCII text (CSV). Listing 1 is the sample XML document, which lists elements from the periodic table.
Listing 1The Periodic Table in XML
<?xml version="1.0"?> <ptable> <element> <name>Hydrogen</name> <symbol>H</symbol> <number>1</number> </element> <element> <name>Lithium</name> <symbol>Li</symbol> <number>3</number> </element> <element> <name>Sodium</name> <symbol>Na</symbol> <number>11</number> </element> <!-- snip --> </ptable>
Next, I need three different stylesheets, one for each format (see Listings 2, 3, and 4).
Listing 2XSLT stylesheet to Generate HTML Output
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <html> <head> </head> <body> <h3>Periodic table of elements</h3> <table border="1" cellspacing="5" cellpadding="5"> <tr> <td align="center">Element name</td> <td align="center">Symbol</td> <td align="center">Atomic number</td> </tr> <xsl:apply-templates /> </table> </body> </html> </xsl:template> <xsl:template match="//element"> <tr> <td align="center"><xsl:value-of select="name" /></td> <td align="center"><xsl:value-of select="symbol" /></td> <td align="center"><xsl:value-of select="number" /></td> </tr> </xsl:template> </xsl:stylesheet>
Listing 3XSLT Stylesheet to Generate CSV Output
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text" omit-xml-declaration="yes" /> <xsl:template match="//element"> <!-- separate the values with commas, put a carriage return at the end of the line --> <xsl:value-of select="concat(name, ', ', symbol, ',', number, '
')" /> </xsl:template> </xsl:stylesheet>
Listing 4XSLT Stylesheet to Generate WML Output
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <wml> <card id="ptable" title="Periodic table"> <p align="center"> Periodic table </p> <xsl:apply-templates /> </card> </wml> </xsl:template> <xsl:template match="//element"> * <xsl:value-of select="name" /> (<xsl:value-of select="symbol" />) - <xsl:value-of select="number" /> <br /> </xsl:template> </xsl:stylesheet>
Finally, I need a PHP script that accepts the file format as argument, picks up the correct stylesheet, and combines it with the XML document to generate appropriate output (see Listing 5).
Listing 5Generating Output in Different Formats Using XSLT and PHP
<?php // alter this to see other formats $format = "csv"; // set the filenames $xml_file = "ptable.xml"; // pick the XSLT sheet based on the $format variable $xslt_file = "ptable_" . $format . ".xsl"; // set the name for the output file $out_file = "/www/ptable." . $format; // create the XSLT processor $xp = xslt_create() or die("Could not create XSLT processor"); // log messages xslt_set_log($xp, "/tmp/xslt.log"); // define the error handler xslt_set_error_handler($xp, "errHandler"); // process the files and write the output to $out_file if(xslt_process($xp, $xml_file, $xslt_file, $out_file)) { echo "Success!"; } // free the resources occupied by the handler xslt_free($xp); // custom error handler function errHandler($processor, $level, $ecode, $einfo) { echo "<html><head></head><body>Something bad just happened. Here's some more information: <br>"; // iterate through error array while(list($key, $value) = each($einfo)) { echo "$key --> $value <br>"; } echo "</body></html>"; } ?>
Nothing too complicated here. The $format variable specifies the file format required, and may be passed to the script either on the command line or as a form variable. Depending on the value of this variable, the appropriate stylesheet is used to generate corresponding output. This output may be displayed or saved to disk for later use (which is what Listing 5 does).
In this case, I specified a filename as the fourth argument to xslt_process()this is the file to which the results of the transformation are written. If I'd omitted this file, the output would have been returned as a string.
About This Article
This article is excerpted from XML and PHP by Vikram Vaswani (New Riders Publishing, 2002). Refer to Chapter 4, "PHP and Extensible Stylesheet Language Transformations (XSLT)," for more detailed information on the material covered in this article, or drop by the PHP section on the Melonfire web site for more tutorials.