Introduction
· A programming language
· Placement of XSLT scripts
· A sample XSLT script
· Checkpoint
How does XSLT work?
· XSLT analyzes XML data
· XSLT templates
· Start an XSLT style sheet
· Create the root template
· Output HTML code
· How to output content
· Checkpoint
Templates
· Template rules
· Creating the template
· Applying a template rule
· XSLT command summary
· Batch Processing Nodes
· Sorting Nodes
· Sorting options
· Conditional processing
· Checkpoint
XML employees example
· Show employees
Exercise
XSLT Server vs. Client
· XML server scripting
· Server script example
· Before XML server scripting
· After XML server scripting
· XML-XSL user sorts
Mastery test
Top of page
References
WAP (W3Schools Intro)
WAP (W3Schools Basic)
XML Applications (W3Schools)
XML 101
XML Tutorial (W3Schools)
Biztalk
Navigation

24. XSLT Introduction

Introduction

XSLT (Extensible Style sheet Language Transformations) transforms XML from static text storage and transmission format to an active information source. The information can then be queried and manipulated to provide meaningful output for humans, or it can be passed on to another computer program.

In short XSLT provides a method for displaying XML data meaningfully on the Web and for re-formatting content for use on any platform. XSLT, for example, is routinely used to reformat XML and HTML markup for WML.

XSLT is still in its infancy -- W3C released its recommendations for XSLT in November 1999. XSLT is a very powerful technology but it's not yet mature. Because of this, we can expect to see XSLT programming skills increasing in demand over the next few years, as XML becomes a commonplace solution in e-Business applications.


A programming language

XSLT is a high-level programming language, which has its own built-in functions. It provides basic arithmetic abilities, string manipulation and comparison operators. In other words, it has something neither HTML nor XML has, if-then logic.


A sample XSLT script

Let us look at a sample XSLT script that renders an XML file as an HTML table. This script is named cd_catalog.xsl. The left button below the script shows you the XML file which references the XSL file. The right button shows how the XSL file renders the XML file.

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<head>
  <title>CD Catalog Sales</title>
</head>
<body>
  <table border="1" cellpadding="4" style="border-collapse:collapse">
  <tr>
    <th>Title</th>
    <th>Artist</th>
  </tr>
  <xsl:for-each select="CATALOG/CD">
  <tr>
    <td><xsl:value-of select="TITLE" /></td>
    <td><xsl:value-of select="ARTIST" /></td>
  </tr>
  </xsl:for-each>
  </table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>



Checkpoint    (answer then click)

1. What is XSLT, and what is its purpose?

2. What does XSLT have that neither HTML or XML has?

How does XSLT work?

The first thing that the XSLT processor does is analyze the XML document and convert it into a node tree. A node tree is a hierarchical representation of the entire XML document.

A node is nothing more than an individual XML element like a markup tag is an individual element of an HTML document.


XSLT analyzes XML data

In order to analyze and transform XML data, the XSL file must be linked to the XML file. Linking enables the XSL file to read the XML data and create the node tree. Linking is accomplished by having the XML file reference the XSL file. In the example below, the XML file is referencing the cdcatalog.xsl file. In order to link the two files, the line in bold must be placed in the XML file.

<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="cdcatalog.xsl"?>
<CATALOG>
  <CD>
    <TITLE>Empire Burlesque</TITLE>
    <ARTIST>Bob Dylan</ARTIST>
    <COUNTRY>USA</COUNTRY>
    <COMPANY>Columbia</COMPANY>
    <PRICE>10.90</PRICE>
    <YEAR>1985</YEAR>
  </CD>
    etc....
</CATALOG>
Since the XML file references the XSL file, the XML file must be sent to the browser in order for the XSLT style sheet to have any effect. The browser should not run the HTML or the XSL files, only the XML.


XSLT templates

After the processor has identified the nodes, it looks at an XSLT style sheet for instructions on what to do with the nodes. Those instructions are contained in templates. Each template has two parts:

  1. A label that identifies the nodes to which the template can be applied
  2. Instructions about the actual transformation that should take place

The processor automatically looks for a root template, which it applies to the root node of the XML document. Remember that the root node is the outermost element.


Start an XSLT style sheet

You begin an XSLT style sheet by declaring the document as an XSLT style sheet. This is done with the following lines of code:

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

   (rest of XSLT code goes here)

</xsl:stylesheet>

Notice that the XSLT style sheet is actually an XML document and it begins with an XML declaration.


Create the root template

The first thing that the XSLT processor looks for is a template that it can apply to the root node of the XML document. Remember every XML document must have a root node -- the first and last tags represent the root node. Creating a root template will apply the style sheet to the entire XML document. The following code is used to create the root template. It is placed directly inside the xsl:stylesheet element and contains the rest of the XSLT style sheet code.

<xsl:template match="/">

   (rest of XSLT or XML or HTML code goes here)

</xsl:template>


Output HTML code

HTML code is easy to output. Within the template rule tag above, add the HTML code that you would like to output when the particular template is invoked. Look at the sample XSLT style sheet above for an example.


How to output content

After you have created the HTML code that will format a given node's content, the next step is to actually output that content. This is done by:

<xsl:value-of select="expression" />

where expression is the node from the XML document whose content has to be output at this point in the logic.

For example, if you wanted to write CD information such as the title, artist and company to the webpage, you would use the following code:

<xsl:value-of select="TITLE" />
<xsl:value-of select="ARTIST" />
<xsl:value-of select="COMPANY" />

Note: The string value of the node is generally the text that the node contains. If the node has child elements, the string value above includes the text contained in those child elements as well. You can obtain the value of a node by specifying its exact name and relation to the root. For example:

<xsl:value-of select = "CATALOG/CD/TITLE" />

Also keep in mind that XML is case sensitive. Expression values must always be typed the same way as the nodes in the XML file. If the nodes of the XML file are in upper case letters, the expression values in the XSLT style sheet must be also.


Checkpoint    (answer then click)

1. How do you create a root template?

2. How do you output a node's content?


Templates



Template rules

Template rules are modules that specify how a particular part of your source XML document should be output. A template rule has three parts:

  1. The opening tag describes where the template will be applied
  2. The middle tags describe what will be done when a match is found
  3. The closing tag completes the template


Creating the template

A template is created by specifying the following lines:

<xsl:template match="pattern" >
</xsl:template>

The match attribute tells the template which XML element to associate itself with. For example, the following template will be associated with the CD element:

<xsl:template match="CD">
</xsl:template>

Note: to obtain the value of an XML element from within its own template you must use this code.

<xsl:value-of select="." />


Applying a template rule

When you create separate templates for different elements you can call them with the <xsl:apply-templates> Element. The <xsl:apply-templates> element will apply a template rule to the current element or to the current element's child nodes. This elememt can be used in two ways.

This code will apply the corresponding templates for the current element and it's child elements:

<xsl:apply-templates/> 

The select attribute is used to apply the template for the child element that matches the value of the attribute.

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

The following example illustrates both of these uses. By applying templates to the child elements, the title and artist of each CD will be different colors. The left button will show the XSLT code, and the right button will show the final result.




XSLT command summary


XSLT Commands Description
<xsl:for-each>Repeat for each matching node
<xsl:sort>Specify order the templates will be used
<xsl:if test="">Output only those nodes that satisfy a certain condition
<xsl:choose>XSLT case statement tests multiple conditions
<xsl:output />Style and format. Example: <xsl:output method="html"/>
<xsl:strip-space>Ignore white space, as with HTML
<xsl:text>Output the text exactly. Example: <xsl:text>, <xsl:text>


Batch Processing Nodes

The xsl:for-each element is typically used to create HTML tables, where one needs to select different values of a node. Here's how it is done:

<table>
<xsl:for-each select="parent_node">
    <tr>
      <td><xsl:value-of select="child_node1" /></td>
      <td><xsl:value-of select="child_node2" /></td>
    </tr>
</xsl:for-each>
</table>


Sorting Nodes

By default, the nodes are processed in the order in which they appear in a document. You can change this by applying an xsl:sort element to the xsl:apply-templates or xsl:for-each elements. The select attribute allows you to select which attribute to sort with.

<xsl:sort select="criteria" />


Sorting options

By default, the sort order will be ascending. If desired, you can use the order attribute to have the a descending sort order. The data-type attribute will allow you to specify what type of data you are sorting whether it be text or number.

<xsl:sort select="TITLE" order="descending" data-type="text" />

The following example will sort the cd catalog in descending order by price. The left button will have the XSLT code and the right button will have the style sheet results.




Conditional processing

The conditional operators in XSLT are:

  • = (equal)
  • != (not equal)
  • &lt; less than
  • &gt; greater than

These operators can be used test XML data to see if they satisfy certain conditions. You can test XML data by using <xsl:if test="expression"> element or the <xsl:choose> element. The difference between these elements is the number of conditional statements that they can support. The <xsl:if> element can support only one statement while the <xsl:choose> element can support more than one.

<xsl:if> element

The if element can support only one conditional statement. The code inside of the element tags will only be run if the conditional statement is true. The syntax for the if element is:

<xsl:if test="some test">
   code to run if test is true...
</xsl:if>

The following example will only show the CD if the price of it is greater than 9.90.

<xsl:if test="PRICE &gt;'9.90'">
   <tr>
      <td><xsl:value-of select="TITLE"/></td>
      <td><xsl:value-of select="ARTIST"/></td>
      <td><xsl:value-of select="PRICE"/></td>
   </tr>
</xsl:if>

A complete example can be found below.



<xsl:choose> element

The choose element acts like a case statement. Multiple conditional statements can be used to test and display data according to the users needs. The syntax for the choose element is:

<xsl:choose>
   <xsl:when test="PRICE &gt;'10'">
      ... some code ...
   </xsl:when>
   <xsl:otherwise>
      ... some code ....
   </xsl:otherwise>
</xsl:choose>

The <xsl:when> elements contain the conditional statements and function just like the <xsl:if> element. The <xsl:otherwise> element contains the code that will run if no conditions are met. The following example makes each row of a table different colors based on the price of the cd. The buttons below show the full XSLT code and results.

<xsl:choose>
    <xsl:when test="PRICE &gt;'10.50'">
        <tr bgcolor="#fff0f5">
            <td><xsl:value-of select="TITLE"/></td>
            <td><xsl:value-of select="ARTIST"/></td>
            <td><xsl:value-of select="PRICE"/></td>
        </tr>
    </xsl:when>
    <xsl:when test="PRICE &gt;'9.50'">
        <tr bgcolor="#f5f5dc">
            <td><xsl:value-of select="TITLE"/></td>
            <td><xsl:value-of select="ARTIST"/></td>
            <td><xsl:value-of select="PRICE"/></td>
        </tr>
    </xsl:when>
    <xsl:when test="PRICE &gt;'8.50'">
        <tr bgcolor="#faebd7">
            <td><xsl:value-of select="TITLE"/></td>
            <td><xsl:value-of select="ARTIST"/></td>
            <td><xsl:value-of select="PRICE"/></td>
        </tr>
    </xsl:when>
    <xsl:otherwise>
        <tr bgcolor="#e0ffff">
            <td><xsl:value-of select="TITLE"/></td>
            <td><xsl:value-of select="ARTIST"/></td>
            <td><xsl:value-of select="PRICE"/></td>
        </tr>
    </xsl:otherwise>
</xsl:choose>


Alternate row colors

Here is some sample code (parts) used by Matt Berg for reading an XML-based guestbook then rendering alternate colored backgrounds for successive rows in the output table. The code combines choose (used above in examples) with dynamic styling.

<table border="1">
<tr>
    <th>Date</th>
    <th>Guestname</th>
    <th>City</th>
    <th>State</th>
    <th>Country</th>
    <th>e-mail</th>
    <th>Comments</th>
</tr>
<xsl:for-each select="guestbook/guest">
<tr>
  <xsl:attribute name="style">
    <xsl:choose>
        <xsl:when test="position() mod 2 = 0">background-color: white</xsl:when>
        <xsl:otherwise>background-color: #eeeeee</xsl:otherwise>
    </xsl:choose>
  </xsl:attribute>
<td><xsl:value-of select="postdate" /></td>
<td><xsl:value-of select="guestname" /></td>
<td><xsl:value-of select="city" /></td>
<td><xsl:value-of select="state" /></td>
<td><xsl:value-of select="country" /></td>
<td><xsl:value-of select="email" /></td>
<td><xsl:value-of select="comments" /></td>
</tr>
</xsl:for-each>

</table>


Checkpoint    (answer then click)

1. How do you do batch processing, where one needs to select different values of a node?

2. What command would you use to output only those records which contained the string "USA" in the COUNTRY node?

XML employees example

This example comes from a Microsoft Northwind database example. There is an employee XML database that is transformed with XSL in two ways: the XML data is first sorted by employee last name, then transformed into an HTML table. Contrast this method to that of the Microsoft data islands.


Show employees





Exercise

Download students.xml to work on this assignment. Create three separate XSLT style sheets that will do the following sorting and selecting.

  • Output a list of all the students as an HTML table
  • Output a list of all students arranged alphabetically by Lastname
  • Output only those students that are females

Remember to place the line below inside your XML file in order to tell it which Stylesheet to use. Submit the XML file to the browser, not the XSL file to the browser, to see the sorting and selecting effects of XSLT.

<?xml-stylesheet type="text/xsl" href="stylesheetName.xsl"?>

Client-side XSLT vs. Server-side XSLT

One important issue is where to place your XSLT scripts. Should they be placed on the server or on the client machine? One of the factors that has contributed to the popularity of server-side processing is the variation in browser capability.

Currently there are very few browsers in the market that support XML and XSLT processing. In a commercial setting you cannot control the version or type of browser that you client will use.

Thus, if you use client-side XSLT, you are taking a risk concerning the ability of your user's browser to render the page accurately. On the other hand, if you choose server-side XSLT, you can send dynamic and sophisticated XHTML pages that make no unexpected browser demands.


XML server scripting

A difficulty with client-side XML-XSLT solutions is the requirement to have ownership of the XML data file if you wish to use XSLT. Recall that the XSLT reference tag in the CD Catalog example above was embedded in the XML data file. To run the XSLT application, you must run the XML data file. While this is counterintuitive, it works as long as you have the XML data available.


Server script example

A server script in ASP can add several important features to XSLT solutions. First, the XML data can be remote to your source code; anywhere on the internet. Second, you can pass parameters (via querystring or session variables) using server scripts to tailor the XSLT code; making the XSLT more dynamic. A before and after example appears below; it is based on the earlier CD Catalog example.

Before XML server scripting

Here is the run file (catalog.xml) for a client-side XML-XSLT solution. To have the browser run the "cd_catalog.xsl" you must instead submit the XML file to the browser. This arrangement does not change with server-side scripting, but notice in the after example that the XML source data file is not required to be mingled with the call to "cd_catalog.xsl".

catalog.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="cd_catalog.xsl"?>
<CATALOG>
  <CD>
    <TITLE>Empire Burlesque</TITLE>
    <ARTIST>Bob Dylan</ARTIST>
    <COUNTRY>USA</COUNTRY>
    <COMPANY>Columbia</COMPANY>
    <PRICE>10.90</PRICE>
    <YEAR>1985</YEAR>
  </CD>
    etc....
</CATALOG>
cd_catalog.xsl
<?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="/">
    <html>
      <body>
        <table border="1" cellpadding="6" >
        <tr>
          <th>Title</th>
          <th>Artist</th>
        </tr>
       <xsl:for-each select="CATALOG/CD">
          <xsl:if test="ARTIST='Bob Dylan'">
          <tr><td>
               <xsl:value-of select="TITLE" />
               </td><td>
               <xsl:value-of select="ARTIST" />
           </td></tr>
          </xsl:if>
        </xsl:for-each>
        </table>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

After XML server scripting

Here is a short ASP script (catalog.asp) that replaces catalog.xml. The run file is now catalog.asp instead of catalog.xml. It calls the XSLT file (here called cd_catalog_xsl.asp) after it copies the XML data from a remote location.

catalog.asp
<%
response.ContentType="text/xml"
%>
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="cd_catalog_xsl.asp?Artist=Bob Dylan"?>
<!--
The code here illustrates how to address a remote xml data source with xslt.
Also illustrated is using ASP to assist scripting XML,
and using query strings to control the kind of xslt report that will be served.
Look at cd_catalog_xsl.asp below to see how the querystring is used.
-->
<%
dim objHTTP
set objHTTP = Server.CreateObject("Microsoft.XMLHTTP")
objHTTP.Open "GET", _
        "http://www.classAnytime.com/db/catalog.xml",false
objHTTP.Send
response.write(objHTTP.responseText)
set objHTTP = nothing
%>
cd_catalog_xsl.asp
<%
dim artist
artist = request("Artist")
%>
<?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="/">
    <html>
      <body>
        <table border="1" cellpadding="6" >
        <tr>
          <th>Title</th>
          <th>Artist</th>
        </tr>
       <xsl:for-each select="CATALOG/CD">
          <xsl:if test="ARTIST='<% =artist %>'">
          <tr><td>
               <xsl:value-of select="TITLE" />
               </td><td>
               <xsl:value-of select="ARTIST" />
          </td></tr>
          </xsl:if>
        </xsl:for-each>
        </table>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

XML-XSL user sorts

This is a modification of the above asp scripts for the purpose of responding to users requests for sort order of the output table. To run the scripts, copy the source below and include a sort order in the querystring, for instance: catalog_sort.asp?Sort=PRICE.

catalog_sort.asp
<%
response.ContentType="text/xml"
sort=request("Sort")
%>
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl"
        href="cd_catalog_xsl_sort.asp?Sort=<% =Sort %>"?>
<%
dim objHTTP
set objHTTP = Server.CreateObject("Microsoft.XMLHTTP")
objHTTP.Open "GET", _
    "http://www.classAnytime.com/db/cd_catalog.xml",false
objHTTP.Send
response.write(objHTTP.responseText)
set objHTTP = nothing
%>
cd_catalog_xsl_sort.asp
<%
dim OrderBy
OrderBy = request("Sort")
%>
<?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="/">
    <html>
      <head><style>
      th {background-color:gainsboro;text-decoration:underline;cursor:hand}
      table {border-collapse:collapse; border-color:dimgray }
      </style></head>
      <body>
        <table border="1" cellpadding="6" >
        <colgroup span="2" align="left"></colgroup>
        <colgroup span="3" align="right"></colgroup>
        <tr>
          <th onclick="location.href='catalog_sort.asp?Sort=TITLE'">Title</th>
          <th onclick="location.href='catalog_sort.asp?Sort=ARTIST'">Artist</th>
          <th onclick="location.href='catalog_sort.asp?Sort=YEAR'">Year</th>
          <th onclick="location.href='catalog_sort.asp?Sort=COUNTRY'">Country</th>
          <th onclick="location.href='catalog_sort.asp?Sort=PRICE'">Price</th>
        </tr>
        <xsl:for-each select="CATALOG/CD">
          <xsl:sort select="<% =OrderBy %>" />
          <tr><td>
               <xsl:value-of select="TITLE" />
               </td><td>
               <xsl:value-of select="ARTIST" />
               </td><td>
               <xsl:value-of select="YEAR" />
              </td><td>
               <xsl:value-of select="COUNTRY" />
              </td><td>
               <xsl:value-of select="PRICE" />
          </td></tr>
        </xsl:for-each>
        </table>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

XSLT server scrips with PHP

Parallel code to the ASP above is available for PHP. See the example in the PHP lesson.

Mastery test