RU beehive logo ITEC dept promo banner
ITEC 325
2019fall
ibarland

XSLT
value-of, for-each

XSLT basics

XSLT, eXtensible Style Language Transformations, is a domain-specific language for transforming XML trees: that is, taking in one XML tree and producing another — a function from XML trees to XML trees! The end result can be any XML; in practice the most common result is an XHTML document.

For example, consider the input

<my_children>
	<child>
		<name>Logan</name>
		<gender>M</gender>
		<age>7</age>
	</child>
	<child>
		<name>Rebecca</name>
		<gender>F</gender>
		<age>3</age>
	</child>
	<child>
		<name>Lee</name>
		<gender>F</gender>
		<age>2</age>
	</child>
</my_children>
An XSLT program might take this and return a new XML tree:
<html>
  <body>
    <h3>Some Kids</h3>
    <ul>
      <li>Logan, who is 7</li>
      <li>Rebecca, who is 3</li>
      <li>Lee, who is 2</li>
    </ul>
  </body>
</html>

Rather than write such a function in Java or a general-purpose programming language, XSLT is a domain-specific language, specifically invented to make these tree-transformations easy to write. XSLT programs can easily generate new tags/nodes based on the input, re-order existing nodes, or filter out unwanted nodes.

Overview

Building an XSL Style Sheet


One data file, many pages

youtube (3m09s):

Similar to how a web-page (data) can have a css-stylesheet directive (processing), XML data files have a xml-stylesheet tag, with what XSLT file processes them.

It's annoying, that the xml-stylesheet processing instruction should be in the same file as the raw XML data. What if you have one data file, and you want to use it to produce several different views/results? Alas, the usual solution is to fall back to a different technology: Have a php file which prints the xml-stylesheet line, and then require's the XML file:

// The file children.php:
<?xml-stylesheet type="text/xsl" href="children.xsl"?>
<?php
  require('children-data.xml');
?>
In fact, this might happen often enough that you choose to write a php util function — say, renderXMLWith([string] $xmlDataFile, [string] $xslTransformFile ) — which prints out these lines. (So the file being linked to (children.php) actually contains just two lines: requiring utils.php, and then a call to renderXMLWith).


Server-side XSLT

That is: Invoking XSLT via php.

So far, the XSLT we've seen is running client-side: the client requests the .xml file, it sees the <?xml-stylesheet processing instruction, requests the .xsl file, and then does the processing to create the output. This is reasonably well supported in all modern browsers.

Note: If you run locally, not using a web-server at all, and opening via Open File…: Firefox works, but Chrome won't5. You have to open Chrome with the command-line argument --allow-file-access-from-files: on Mac this can be done with /Applications/Google\ Chrome.app/contents/MacOS/Google\ Chrome --allow-file-access-from-files.

But of course, there's nothing inherent about doing the processing on the client. You can create a server-side .php page which, when requested, does the processing, to create the final html result:

Discussion:

You can do this in php as follows: First, omit the <?xml-stylesheet processing-instruction from the .xml file. Then, have a php file which does the following:

<?php
// Load XML file
$xml = new DOMDocument;
$xml->load('xml-database.xml');

// Load XSL file
$xsl = new DOMDocument;
$xsl->load('xsl-program.xsl');

// Configure the transformer
$proc = new XSLTProcessor;

// Attach the xsl rules
$proc->importStyleSheet($xsl);

echo $proc->transformToXML($xml);
?>
       
Source: www.w3schools.com/xsl/xsl_server.asp (This code uses php objects, hence the -> syntax for calling a method.)
a missed opportunity?:

Observe, in the last three lines, that you can can make one XSLTProcessor object which transforms many XML files, all using the same stylesheet.

If you're only serving a single web-page, this is usually moot. It would be useful if you have php prorams that pre-generate many pages. But I can't help wondering: which use-case is more common?

A built-in for helping with the former seems much more likely to be useful; as it is, we have to fall back to doing this manually.


1 Remember, one of the XML requirements is that there is exactly one top-level tag.      
2 The reason for the lack of xsl:else is because it's a bit unclear where the else tag should be placed — conceptually it belongs beside the if tag, but requiring side-by-side tags is unlike any other instruction. Putting the else inside the if makes more sense, but even then the condition attributes now seem placed oddly. A more appropriate version might have an if tag with exactly two children: “then” and “else”. … hey now we've arrived back at what xsl:choose does, except we're limited to exactly-two! I guess they designed the choice tag correctly after all!      
3 Perhaps they should use an English term beside “if”; something like “when” or “unless”?      
4 In php it's no problem to have an expression whose result was inserted into the middle of an attribute. However, since XSLT is itself written in XML, and XML of course doesn't allow opening a tag in the middle of an attribute, the syntax physically precludes putting xsl:select (etc.) expressions in the middle of an attribute.      
5 When rending a local file:// URL, Chrome's XSLT engine sees the stylesheet's URL (if also local) as a security risk, and does not open it by default.      

logo for creative commons by-attribution license
This page licensed CC-BY 4.0 Ian Barland
Page last generated
Please mail any suggestions
(incl. typos, broken links)
to ibarlandradford.edu
Rendered by Racket.