| ||||||||||||||||
24. XSLT IntroductionIntroductionXSLT (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.
|
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> |
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>
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" />
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.
The conditional operators in XSLT are:
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.
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 >'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.
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 >'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 >'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 >'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 >'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>
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>
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?
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.
Download students.xml to work on this assignment. Create three separate XSLT style sheets that will do the following sorting and selecting.
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"?>
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.
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.
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.
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".
<?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>
<?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>
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.
<%
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
%>
<%
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>
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
.
<%
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
%>
<%
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>
Parallel code to the ASP above is available for PHP. See the example in the PHP lesson.