If you are familiar with the Cascading Style Sheets (CSS) specification often used on the Web, you are probably aware that CSS stylesheets can be stored in a separate file, or embedded as a special element within an HTML document. Also, specific styling information can be attached to individual attributes within the document. In this section, we examine the corresponding approaches to using XSLT.
Each of the three ways of using CSS have an analogous technique using XSLT, but the XSLT stylesheets are substantially more powerful. While this discussion refers to some specific XSLT elements and shows several in the examples, it does not expect that you know anything about them. These elements are described in more detail later in this chapter; this section simply introduces you to the ways stylesheets can be written and how that relates to the documents being processed.
Simplified stylesheets are more like using the STYLE attribute in HTML
documents than anything else, but the similarity is minimal. This
approach is somewhat less powerful than using embedded or standalone
stylesheets; the xsl:stylesheet
element is not allowed since the entire stylesheet is interpreted as
the body of an xsl:template
element. Many features of XSLT require using additional “top-level”
elements (peers of the xsl:template
element), so they are not allowed in this context. This kind of
stylesheet is more difficult to use when the basic structure of the
source document needs to be preserved, but is perfectly able to make
queries about the structure and content of the source document.
Simplified stylesheets are most often applied when the output
documents are very regular and only need to extract very specific
portions of the input document.
Since simplified stylesheets are also about the easiest to start with when learning XSLT, let’s take a look at one. In the previous chapter, we use a list of spaceships from a group of well-known television shows to provide input data (see Example 5-1); we use that input here as well. Instead of using the DOM and XPath to retrieve a list of nodes, we use XSLT to create a list of spaceships sorted by their registry numbers, nicely presented as an HTML table. Example 6-1 shows the stylesheet. Notice the root element of the stylesheet document declares the namespace for XSLT and specifies the XSLT version that is being used; these are required for the use of simplified stylesheets.
<html xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xsl:version="1.0"> <head> <title>Ships of the <xsl:value-of select="/shiptypes/@name" /></title> </head> <body> <table border="1"> <tr><th>Ship</th> <th>Class</th> <th>Registration</th> <th>Captain</th> </tr> <xsl:for-each select="/shiptypes/ship"> <xsl:sort select="registry-code" /> <tr><td><xsl:value-of select="@name" /></td> <td><xsl:value-of select="class" /></td> <td><xsl:value-of select="registry-code" /></td> <td><xsl:value-of select="captain" /></td> </tr> </xsl:for-each> </table> </body> </html>
The result of processing the ships.xml file from Example 5-1 with the stylesheet ships-template.html in Example 6-1 is given in ships.html, shown in Example 6-2. The transformation was performed using 4XSLT.
<html> <head> <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'> <title>Ships of the United Federation of Planets</title> </head> <body> <table border="1"> <tr> <th>Ship</th> <th>Class</th> <th>Registration</th> <th>Captain</th> </tr> <tr> <td>USS Enterprise</td> <td>Constitution</td> <td>NCC-1701</td> <td>James T. Kirk</td> </tr> <tr> <td>USS Enterprise</td> <td>Galaxy</td> <td>NCC-1701-D</td> <td>Jean-Luc Picard</td> </tr> <tr> <td>USS Enterprise</td> <td>Sovereign</td> <td>NCC-1701-E</td> <td>Jean-Luc Picard</td> </tr> <tr> <td>USS Voyager</td> <td>Intrepid</td> <td>NCC-74656</td> <td>Kathryn Janeway</td> </tr> <tr> <td>USS Sao Paulo</td> <td>Defiant</td> <td>NCC-75633</td> <td>Benjamin L. Sisko</td> </tr> </table> </body> </html>
Note that the transformation added a meta
element near the top of the generated
HTML, and that the indentation and whitespace inside the replacement
for the xsl:for-each
element has
been adjusted somewhat. Figure
6-2 shows what the resulting HTML document looks like in a web
browser.
Stylesheets stored in separate files are perhaps the
most commonly used form of stylesheets for both CSS and XSLT. The root
element of the stylesheet must be an xsl:stylesheet
or xsl:transform
element. This is what we use
for most of the examples in this book. Standalone stylesheets offer
more power and flexibility than simplified stylesheets, and lend
themselves to better modularization, allowing use of a powerful import
mechanism as well as strong pattern matching abilities.
Let’s look at the previous example expressed as a standalone
stylesheet. We could use a trivial wrapper around the template
document to create a stylesheet that is technically correct, but let’s
go ahead and change it to reflect a more typical way of structuring a
stylesheet. This particular version no longer sorts the table of
ships, but maintains their order from the original document. This is a
common way of structuring a stylesheet for a document-oriented
application. Our new stylesheet is shown in Example 6-3. Notice that the
XSLT namespace is declared here as well, along with the version
attribute, but we need not include
the namespace prefix when the attribute is attached to an xsl:stylesheet
element.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="/"> <html> <head> <title>Ships of the <xsl:apply-templates mode="head" /></title> </head> <body> <xsl:apply-templates /> </body> </html> </xsl:template> <xsl:template match="shiptypes" mode="head"> <xsl:value-of select="@name" /> </xsl:template> <xsl:template match="shiptypes"> <table border="1"> <tr><th>Ship</th> <th>Class</th> <th>Registration</th> <th>Captain</th> </tr> <xsl:apply-templates /> </table> </xsl:template> <xsl:template match="ship"> <tr><td><xsl:value-of select="@name" /></td> <td><xsl:value-of select="class" /></td> <td><xsl:value-of select="registry-code" /></td> <td><xsl:value-of select="captain" /></td> </tr> </xsl:template> </xsl:stylesheet>
This version is structured as a set of templates that
match particular constructs in the input document; the matched
constructs are specified by the match
attribute of the xsl:template
elements. The XSLT constructs
used in this stylesheet are explained in detail later in this chapter.
Example 6-4 shows the
result of transforming ships.xml
(see Example 5-1) using
ships.xsl (see Example 6-3).
<html> <head> <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'> <title>Ships of the United Federation of Planets</title> </head> <body> <table border="1"> <tr> <th>Ship</th> <th>Class</th> <th>Registration</th> <th>Captain</th> </tr> <tr> <td>USS Enterprise</td> <td>Sovereign</td> <td>NCC-1701-E</td> <td>Jean-Luc Picard</td> </tr> <tr> <td>USS Voyager</td> <td>Intrepid</td> <td>NCC-74656</td> <td>Kathryn Janeway</td> </tr> <tr> <td>USS Enterprise</td> <td>Galaxy</td> <td>NCC-1701-D</td> <td>Jean-Luc Picard</td> </tr> <tr> <td>USS Enterprise</td> <td>Constitution</td> <td>NCC-1701</td> <td>James T. Kirk</td> </tr> <tr> <td>USS Sao Paulo</td> <td>Defiant</td> <td>NCC-75633</td> <td>Benjamin L. Sisko</td> </tr> </table> </body> </html>
The only difference between this output and Example 6-2 is that the table is not sorted in this version.
XSLT stylesheets can be embedded within other documents
in much the same way that CSS stylesheets can be embedded in an HTML
document. When embedding an XSLT stylesheet, it is typically embedded
in the document to which it applies. The embedded element must be the
xsl:stylesheet
(or xsl:transform
) element. This usage pattern
is not commonly used since it doesn’t allow the stylesheet to be
re-used as easily with other documents, and few XSLT processors
support embedded stylesheets. Given the lack of broad tool support for
embedded stylesheets, we won’t bother showing any examples.