2.3. Another XSLT Example, Using XHTML
Example 2-5 contains XML data from an imaginary scheduling
program. A schedule has an owner followed by a list of appointments.
Each appointment has a date, start time, end time, subject, location,
and optional notes. Needless to say, a true scheduling application
probably has a lot more data, such as repeating appointments, alarms,
categories, and many other bells and whistles. Assuming that the
scheduler stores its data in XML files, we can easily add features
later by writing a stylesheet
to convert the existing XML files to some new format.
Example 2-5. schedule.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="schedule.xslt"?>
<schedule>
<owner>
<name>
<first>Eric</first>
<last>Burke</last>
</name>
</owner>
<appointment>
<when>
<date month="03" day="15" year="2001"/>
<startTime hour="09" minute="30"/>
<endTime hour="10" minute="30"/>
</when>
<subject>Interview potential new hire</subject>
<location>Rm 103</location>
<note>Ask Bob for an updated resume.</note>
</appointment>
<appointment>
<when>
<date month="03" day="15" year="2001"/>
<startTime hour="15" minute="30"/>
<endTime hour="16" minute="30"/>
</when>
<subject>Dr. Appointment</subject>
<location>1532 Main Street</location>
</appointment>
<appointment>
<when>
<date month="03" day="16" year="2001"/>
<startTime hour="11" minute="30"/>
<endTime hour="12" minute="30"/>
</when>
<subject>Lunch w/Boss</subject>
<location>Pizza Place on First Capitol Drive</location>
</appointment>
</schedule>
As
you can see, the XML document uses both attributes
(month="03") and child elements to represent its
data. XSLT has the ability to search for and transform both types of
data, as well as comments, processing instructions, and text. In our
current document, the appointments are stored in chronological order.
Later, we will see how to change the sort order using
<xsl:sort>.
Unlike the earlier example, the second line of Example 2-5 contains a reference to the XSLT stylesheet:
<?xml-stylesheet type="text/xsl" href="schedule.xslt"?>
This processing instruction is entirely optional. When viewing the
XML document in a web browser that supports XSLT, this is the
stylesheet that is used. If you apply the stylesheet from the command
line or from a server-side process, however, you normally specify
both the XML document and the XSLT document as parameters to the
processor. Because of this capability, the processing instruction
shown does not force that particular stylesheet to be used. From a
development perspective, including this line quickly displays your
work because you simply load the XML document into a compatible web
browser, and the stylesheet is loaded automatically.
NOTE:
In this book, the xml-stylesheet processing instruction uses type="text/xsl". However, some processors use type="text/xml", which does not work with Microsoft Internet Explorer. The XSLT specification contains one example, which uses "text/xml".
Figure 2-3 shows the XHTML output from an XSLT
transformation of schedule.xml. As you can see,
the stylesheet is capable of producing content that does not appear
in the original XML data, such as "Subject:". It
can also selectively copy element content and attribute values from
the XML source to the result tree; nothing requires every piece of
data to be copied.
Figure 2-3. XHTML output
The XSLT stylesheet that produces this output is shown in Example 2-6. As mentioned previously, XSLT stylesheets
must be well-formed XML documents. Once again, we use
.xslt as the
filename extension, but
.xsl is also common. This stylesheet is based on
the skeleton document presented in Example 2-4.
However, it produces XHTML instead of HTML.
Example 2-6. schedule.xslt
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"
doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/>
<!--****************************************************************
** "/" template
*************************************************************-->
<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Schedule</title>
</head>
<body>
<h2 align="center">
<xsl:value-of select="schedule/owner/name/first"/>
<xsl:text disable-output-escaping="yes">&nbsp;</xsl:text>
<xsl:value-of select="schedule/owner/name/last"/>'s Schedule</h2>
<xsl:apply-templates select="schedule/appointment"/>
</body>
</html>
</xsl:template>
<!--***************************************************************
** "appointment" template
************************************************************-->
<xsl:template match="appointment">
<hr/>
<h3>Appointment</h3>
<xsl:apply-templates select="when"/>
<table>
<tr>
<td>Subject:</td>
<td>
<xsl:value-of select="subject"/>
</td>
</tr>
<tr>
<td>Location:</td>
<td>
<xsl:value-of select="location"/>
</td>
</tr>
<tr>
<td>Note:</td>
<td>
<xsl:value-of select="note"/>
</td>
</tr>
</table>
</xsl:template>
<!--****************************************************************
** "when" template
*************************************************************-->
<xsl:template match="when">
<p>
<xsl:value-of select="date/@month"/>
<xsl:text>/</xsl:text>
<xsl:value-of select="date/@day"/>
<xsl:text>/</xsl:text>
<xsl:value-of select="date/@year"/>
from
<xsl:value-of select="startTime/@hour"/>
<xsl:text>:</xsl:text>
<xsl:value-of select="startTime/@minute"/>
until
<xsl:value-of select="endTime/@hour"/>
<xsl:text>:</xsl:text>
<xsl:value-of select="endTime/@minute"/>
</p>
</xsl:template>
</xsl:stylesheet>
The first part of this stylesheet should look familiar. The first
four lines are typical of just about any stylesheet you will write.
Next, the output method is specified as xml
because this stylesheet is producing XHTML instead of HTML:
<xsl:output method="xml"
doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/>
The <xsl:output> element produces the
following XHTML content:
<?xml version="1.0" encoding="UTF-16"?>
<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
Moving on, the first template in the stylesheet matches
"/" and outputs the skeleton for the XHTML
document. Another requirement for XHTML is the namespace attribute on
the <html> element:
<html xmlns="http://www.w3.org/1999/xhtml">
The remainder of schedule.xslt consists of
additional templates, each of which matches a particular pattern in
the XML input.
NOTE:
Because of its XML syntax, XSLT stylesheets can be hard to read. If you prefix each template with a distinctive comment block as shown in Example 2-6, it is fairly easy to see the overall structure of the stylesheet. Without consistent indentation and comments, the markup tends to run together, making the stylesheet much harder to understand and maintain.
The <xsl:text> element is used to insert
additional text into the result tree. Although plain text is allowed
in XSLT stylesheets, the <xsl:text> element
allows more explicit control over whitespace handling. As shown here,
a nonbreaking space is inserted into the result tree:
<xsl:text disable-output-escaping="yes">&nbsp;</xsl:text>
Unfortunately, the following syntax does not work:
<!-- does not work... -->
<xsl:text> </xsl:text>
This is because is not one of the five
built-in entities supported by XML. Since XSLT stylesheets are always
well-formed XML, the parser complains when
is found in the stylesheet. Replacing
the first ampersand character with &
allows the XML parser to read the stylesheet into memory. The XML
parser interprets this entity and sends the following markup to the
XSLT processor:
<!-- this is what the XSLT processor sees, after the XML parser
interprets the & entity -->
<xsl:text disable-output-escaping="yes"> </xsl:text>
The second piece of this solution is the
disable-output-escaping="yes" attribute. Without
this attribute the XSLT processor may attempt to escape the
nonbreaking space by converting it into an actual character. This
causes many web browsers to display question marks because they
cannot interpret the character. Disabling output escaping tells the
XSLT processor to pass to the result
tree. Web browsers then interpret and display the nonbreaking space
properly.
In the final template shown in Example 2-6, you may
notice the element <xsl:value-of
select="date/@month"/>. The @
character represents an attribute, so in this case the stylesheet is
outputting the value of the month attribute on the date element. For
this element:
<date month="03" day="15" year="2001"/>,
the value "03" is copied to the result
tree.
 |  |  | 2.2. Transformation Process |  | 2.4. XPath Basics |
Copyright © 2002 O'Reilly & Associates. All rights reserved.
|