QRdvark.com

XML And XSL

XML And XSL

By Kevin Waterson

Contents

  1. Abstract
  2. Getting Started
  3. Include XSL
  4. Import XSL
  5. Creating XML From Database Results
  6. Creating a Menu

Abstract

XML is the true language of the web when it comes to data transfer. Even the humble HTML markup language is a subset of XML. The strength of XML is that it is easily machine readable. This strength is also is greatest weakness when it comes to rendering the data into a human readable format. Enter XSL. XSL provides the ability to transform XML documents into HTML and so, render them human readable. This tutorial will demonstrate how to achieve this and some of the possible applications.

This tutorial requires a fundamental understanding of XML and a clue. If you lack the first, you may still get by. A pre-requisite is a PHP installation with XML and XSL extensions. Check phpinfo() for these extensions.

Getting Started

To get started, we need an XML document. As is traditional with these tutorials, a book collection will be used as an example. The first file will be called doc.xml and will contain the XML with the information about the books.

<collection>
 <book>
  <title>Pro PHP</title>
  <author>Kevin McArthur </author>
  <isbn>1590598199</isbn>
 </book>
 <book>
  <title>Practical Web 2.0 Applications with PHP</title>
  <author>Quentin Zervaas</author>
  <isbn>1590599063</isbn>
 </book>
</collection>

The second file will called doc.xsl and and will contain the markup XSL for the XML in the first file.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:param name="owner" select="'QRdvark.com'"/>
 <xsl:output method="html" encoding="iso-8859-1" indent="no"/>
 <xsl:template match="collection">
 <h1><xsl:value-of select="$owner"/> book store</h1>
  <xsl:apply-templates/>
 </xsl:template>
 <xsl:template match="book">
  <h3><xsl:value-of select="title"/></h3>
  <h4>by <xsl:value-of select="author"/> - <xsl:value-of select="isbn"/></h4>
  <hr />
 </xsl:template>
</xsl:stylesheet>

The third file will be called doc.php and will bring together the XSL and XML.


<?php

$xml_file 
'doc.xml';

$xsl_file 'doc.xsl';

$doc = new DOMDocument();
$xsl = new XSLTProcessor();

$doc->load($xsl_file);
$xsl->importStyleSheet($doc);

$doc->load($xml_file);
echo 
$xsl->transformToXML($doc);

?>

With the above three files in place, and accessing doc.php with a web browser, the results should look a little like this.

QRdvark.com book store

Pro PHP

by Kevin McArthur - 1590598199


Practical Web 2.0 Applications with PHP

by Quentin Zervaas - 1590599063


Lets pause here and look at what has happened in the code above. The XML file contains information about books in a collection, a very small collection of two. The XML itself is nested within a parent, or root, node called collection. Within the collection node, are two book nodes. Each of the book nodes, contains information about a book.

  • Title
  • Author
  • ISBN

The XSL file is where the markup happens. The file contains several key instructions about how the information in the XML should be displayed, beginning with this line.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

This line tells what type of document it is, and defines it as an xsl stylesheet. Following this a parameter is defined for the owner of the collection. The param is given the name "owner" and is available from anywhere within the stylesheet by its variable name, in this case, $owner. This in turn, is followed by the type of output. This is a key factor in displaying the end result. The output method is defined as html and an encoding type is supplied with it. Other output methods include XML or text.

Beginning with the template match, the real markup begins. The template match is set to the root of the XML tree and from there all other nodes "branch" off.

Soon after the template match is set once more to "book". This tells the parser that the root is now the book node, and any interactions should regard the path to other nodes in this way.

In the PHP document, the XML and XSL documents are brought together. The PHP creates a new DOM object and a new XSLProcessor object. The XSL document is loaded into the DOM (Document Object Model) and the XSL stylesheet imported with the importStyleSheet() function.

The XML document is then loaded into the DOM, and with the use of the transformToXML() function, the merger is complete and the output is now valid HTML.

Just to show the flexibility of the XML and XSL method, lets add a third book to the XML file so that doc.xml file looks like this.

<collection>
 <book>
  <title>Pro PHP</title>
  <author>Kevin McArthur </author>
  <isbn>1590598199</isbn>
 </book>
 <book>
  <title>Practical Web 2.0 Applications with PHP</title>
  <author>Quentin Zervaas</author>
  <isbn>1590599063</isbn>
 </book>
 <book>
  <title>Extending and Embedding PHP</title>
  <author>Sara Golman</author>
  <isbn>978-0672327049</isbn>
 </book>
</collection>

Now refresh the doc.php page and the output will look a little like this.

QRdvark.com book store

Pro PHP

by Kevin McArthur - 1590598199


Practical Web 2.0 Applications with PHP

by Quentin Zervaas - 1590599063


Extending and Embedding PHP

by Sara Golman - 978-0672327049


Without any additional code in the PHP or XSL, the new book has been added to the output. Of course, the source of the XML could be from anywhere on the net making a very flexible system.

Including Stylesheets

In real world situations, sites and applications built with XML and XSL rely on a system of templates, long before the attempts to mimic this behavior with PHP code. However, the principle is the same. The base template contains an include statement which includes a template as if code had been part of the parent template all along. This is achieved with the <xsl:include /> function. Lets break the doc.xsl file into two parts, with the parent file to include a file called "booklist.xsl". These files will now look like this:

doc.xsl

 <xsl:param name="owner" select="'QRdvark.com'"/>
 <xsl:output method="html" encoding="iso-8859-1" indent="no"/>
 <xsl:template match="collection">
 <h1><xsl:value-of select="$owner"/> book store</h1>
  <xsl:apply-templates/>
 </xsl:template>

  <xsl:include href="booklist.xsl"/>


booklist.xsl

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:template match="book">
  <h3><xsl:value-of select="title"/></h3>
  <h4>by <xsl:value-of select="author"/> - <xsl:value-of select="isbn"/></h4>
  <hr />
 </xsl:template>
</xsl:stylesheet>

Note that the booklist.xsl file is a complete xsl stylesheet in itself and has an appropriate stylesheet declaration at the top and an ending tag to finish. Without these, the document is not a valid XSL file for inclusion and will produce an error.

The result of this code will produce exactly the same as used in the first example, so why bother? This method allows the importing of any stylesheet and may be dependent on a condition as to which stylesheet is included. This type of "template language" has been around for some time and is very flexible.

Import XSL

The xsl:import works in exactly the same way as xsl:include that is demonstrated above, with a single exception. In an imported style sheet, directives in the stylesheet that is imported can be be overridden by directives in the parent stylesheet that imports it. Lets make some small alterations to the files above, so that the booklist.xsl file is imported rather than included in the doc.xsl file.

doc.xsl


<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:import href="booklist.xsl"/>

 <xsl:param name="owner" select="'QRdvark.com'"/>
 <xsl:output method="html" encoding="iso-8859-1" indent="no"/>
 <xsl:template match="collection">

 <h1><xsl:value-of select="$owner"/> book store</h1>
  <xsl:apply-templates/>
 </xsl:template>

</xsl:stylesheet>

booklist.xsl


<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="collection">
 <b><xsl:value-of select="$owner"/> book store</b>
  <xsl:apply-templates/>
 </xsl:template>

 <xsl:template match="book">
  <h3><xsl:value-of select="title"/></h3>
  <h4>by <xsl:value-of select="author"/> - <xsl:value-of select="isbn"/></h4>
  <hr />
 </xsl:template>
</xsl:stylesheet>

Note in the code above that both the doc.xsl (parent) and the imported (child) document both of have template matches for the collection and apply different styles to the selector for owner. However, the imported style is ignored as the parent takes precedence. and the result looks like this.

QRdvark.com book store

Pro PHP

by Kevin McArthur - 1590598199


Practical Web 2.0 Applications with PHP

by Quentin Zervaas - 1590599063


Extending and Embedding PHP

by Sara Golman - 978-0672327049


Also note that the import line should be before any other style.

Creating XML From Database Results

In the previous examples the XML has been contained in a single file. But this is not always the case, as data sources vary depending on the application. Sometimes they will be in an array and more often, the data will be derived from a database result set. Of course, this data is not XML and to apply an XSL stylesheet to it, it needs to be the form of an XML document. With the use of the PHP DOM extension, the database result set can be traversed, and the resulting data put into XML tags matching the name of the database field from which it came.

This topic has been moved into a class of its own and can be found at https://QRdvark.com/classes/PDO2XML.html

An XML Menu

Lets begin by adding a little to our XML document. All that is required is a URL node so that a link can be created to the books location on Amazon. This is the only change needed to the XML as shown here.


<collection>
 <book>
  <title>Pro PHP</title>
  <author>Kevin McArthur </author>
  <isbn>1590598199</isbn>
  <url>http://www.amazon.com/Pro-PHP-Patterns-Frameworks-Testing/dp/1590598199</url>
 </book>
 <book>
  <title>Practical Web 2.0 Applications with PHP</title>
  <author>Quentin Zervaas</author>
  <isbn>1590599063</isbn>
  <url>http://www.amazon.com/Practical-Web-2-0-Applications-PHP/dp/1590599063</url>
 </book>
 <book>
  <title>Extending and Embedding PHP</title>
  <author>Sara Golman</author>
  <isbn>978-0672327049</isbn>
  <url>http://www.amazon.com/Extending-Embedding-PHP-Developers-Library/dp/067232704X</url>
 </book>
</collection>

To render this list of books, and link them to the URL provided in the <url> node, the use of the attribute href is employed. This attribute tells the stylesheet that the data that follows is a hypertext link. In this example the XSL document is extended a little to include some HTML as would be seen in the real world.


<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="collection">
<html>
<head>
<title>Menu</title>
</head>
<body>

<xsl:apply-templates select="book" />

</body>
</html>
</xsl:template>

<xsl:template match="collection">
<ul>
<xsl:for-each select="book">
<li>
        <a class="text">
        <xsl:attribute name="href">
        <xsl:value-of select="url"/>
        </xsl:attribute>
        <xsl:value-of select="title"/>
        </a>
</li>
</xsl:for-each>
</ul>
</xsl:template>
</xsl:stylesheet>

Then using the same doc.php as used previously, will product a list something like this..

A shorter and perhaps more direct approach to creating the links can be achieved in the XSL document as shown below.


<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="collection">
<html>
<head>
<title>Menu</title>
</head>
<body>

<xsl:apply-templates select="book" />

</body>
</html>
</xsl:template>

<xsl:template match="collection">
<ul>
<xsl:for-each select="book">
<li>
        <a href="{url}"><xsl:value-of select="title"/></a>
</li>
</xsl:for-each>
</ul>
</xsl:template>
</xsl:stylesheet>