Tony Marston's Blog About software development, PHP and OOP

Performing client-side XSL transformations

Posted on 11th December 2005 by Tony Marston

Amended on 21st June 2006

Introduction
Software changes
Try it out
Browser bugs
Amendment History
Comments

Introduction

It is a feature of my software that I produce HTML output from XML documents with server-side XSL transformations. This means that as well as producing the XML document I transform it into HTML on the server before I send the result to the client.

However, performing XSL transformations on the server does increase the load on the server. Although the speed of XSL transformations has increased significantly with PHP 5 there are still a large number of web hosts running PHP 4. There are even a number of web hosts which do not have the XSLT extension enabled.

Browser support for XSLT is increasing, with both Internet Explorer 6 and Firefox leading the way, so if you are using one of these browsers then it is worth considering as an option.

This article will show the changes I have made to my software to support client-side XSL transformations, so if you have a suitable browser you can try it out for yourself.

Software changes

Making the change was actually quite straightforward. One difference is that when I create my XML document instead of this:

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <foobar>
  ....
  </foobar>
</root>

I must add an extra line to identify that an XSL transformation is required, and the URL of the XSL stylesheet that should be used to perform the transformation, as shown below:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="HTTP://www.tonymarston.net/foobar.xsl"?>
<root>
  <foobar>
  ....
  </foobar>
</root>

This extra line is not required for server-side XSL transformations as the XML and XSL documents are supplied as separate inputs to the XSLT processor.

The second change was to tell my software which type of XSL processing is required - client-side or server-side. I decided to make this feature switchable at runtime so that it could be turned on or off at will. To do this I look for an argument in the $_GET array with the name csxslt (for Client-Side XSL Transformations) which can have a value of either ON or OFF.

The following codes takes any value from the $_GET array (if present) and stores it in the $_SESSION array where it is preserved until the end of the session.

    if (!array_key_exists('XSLT_client_side', $_SESSION)) {
        $_SESSION['XSLT_client_side'] = FALSE;
    } // if
    if (isset($_GET['csxslt'])) {
        $_SESSION['XSLT_client_side'] = $_GET['csxslt'];
    } // if

Note also that the value for XSLT_client_side will also be stored in a cookie.

There is also the option to turn this flag on permanently by adding the line $GLOBALS['XSLT_client_side'] = true; to the config.inc file. Provided that this option is not being used the setting for XSLT_client_side can be altered on any web page simply by appending csxslt=on/off to the URL.

When the XML document is complete I decide what to do with it using the following code:

    if (is_true($_SESSION['XSLT_client_side'])) {
        // send XML file to the client for transformation there
        XSLclient($xml_string);
    } else {
        // transform XML document into HTML using XSL file
        XSLTransform($xml_string, $xsl_file);
    } // if

It is the XSLclient() function that sends the raw XML to the client's browser:

function XSLclient ($xml_string)
// send the XML file to the client so that it can be transformed into HTML there
{
    // set charset to display accented characters correctly
    header('content-type: application/xml; charset=UTF-8');

    // disable any caching by the browser
    header('Expires: Mon, 14 Oct 2002 05:00:00 GMT'); // Date in the past
    header('Last-Modified: ' .gmdate("D, d M Y H:i:s") .' GMT'); // always modified
    header('Cache-Control: no-store, no-cache, must-revalidate'); // HTTP 1.1
    header('Cache-Control: post-check=0, pre-check=0', false);
    header('Pragma: no-cache'); // HTTP 1.0

    echo $xml_string;

    return;

} // XSLclient

While the pages were transformed without problem by IE6 there were a few difficulties with Firefox which were resolved as follows:

There. That's all there is to it.

Try it out

If you want to try this out you can do so by clicking on the relevant link in http://www.tonymarston.net/sample/index.html. It is interesting to note that Firefox is significantly faster and smoother than that *other* browser.

If your browser displays the output as one long unformatted string then you need to slap it into submission my hitting REFRESH a couple of times followed by BACK.

Browser Bugs

Watch out for the following browser bugs when performing client-side transformations:

Firefox Due to bug #98168 it cannot handle the "disable-output-escaping" option, which means that the ability to include fragments of HTML code in files header.txt and footer.txt will not work. Plain text is OK, but the '<' and '>' around any HTML tags will be converted to '&lt;' and '&gt;'.
Internet Explorer IE is unable to navigate from an HTTPS page to an HTTP page. Even though it receives the HTTP page (as shown in the URL) it reports an error with the previous page which was delivered via HTTPS. The only way I can get around this problem is to ignore HTTPS when performing client-side XSL transformations with IE.

Amendment History

21st June 2006 Added a new section for Browser bugs.

counter