Creating Stylesheets

Because XSLT documents are also XML documents, the XSLT 1.0 specification defines a number of elements to let you create stylesheets. XSLT uses XPath to let you specify exactly what data you want to work with in the XML document, and we'll be assigning XPath expressions to the match and select attributes of XSLT elements in this chapter.

As introduced in Chapter 1, XSLT stylesheets begin with an XML declaration and the <xsl:stylesheet> element (note that this is not the <?xsl:stylesheet?> processing instruction you can use in XML documents to connect stylesheets to XML documents). In this element, we associate the xsl namespace with the URI "http://www.w3.org/1999/XSL/Transform", which is the official namespace for XSLT:

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

To specify what elements you want to locate and work with, you use the <xsl:template> element to create XSLT templates.

Creating Templates

A template uses an XPath expression to match a node or nodes in your XML document and lets you specify what you want to do with the matched data. For example, to match the document element, <planets> , in our XML document, we use this <xsl:template> element:

 
 <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">  <!-- This template matches all planets elements -->   <xsl:template match="planets">   .   .   .   </xsl:template>  .         .         . </xsl:stylesheet> 

The XSLT processor will look through the XML document and match the <planets> element to this template. The XSLT processor automatically opens the document, starts at the root node, and searches for templates that match the children of the root node. In this case, that means <xsl:template match="planets"> will match, because <planets> is a child of the root node (but <xsl:template match="planet"> would not match because <planet> is a grandchild of the root node).

The template replaces the node(s) you've matched with the content you specify. In this case, we want to create a new HTML table displaying our planetary data and use the <xsl:apply-templates/> to handle the child elements of the <planets> element:

 
 <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.1"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">     <!-- This template matches all planets elements -->     <xsl:template match="/planets">  <HTML>   <HEAD>   <TITLE>   The Planets Table   </TITLE>   </HEAD>   <BODY>   <H1>   The Planets Table   </H1>   <TABLE BORDER="2">   <TR>   <TD>Name</TD>   <TD>Mass</TD>   <TD>Radius</TD>   <TD>Day</TD>   </TR>   <xsl:apply-templates/>   </TABLE>   </BODY>   </HTML>  </xsl:template>         .         .         . 

Note in particular that you use the <xsl:apply-templates> element, as we've done here, to indicate that you've got other templates to use on the child nodes of the current node.

Applying Templates for Child Nodes

In our case, we're using <xsl:apply-templates> to work with the child nodes of the <planets> element, and we'll use a new template to indicate that we want to match <planet> elements like this:

 
 <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.1"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">     <!-- This template matches all planets elements -->     <xsl:template match="/planets">         <HTML>         .         .         .  <xsl:apply-templates/>  .         .         .         </HTML>     </xsl:template>  <xsl:template match="planet">   <TR>   <TD><xsl:value-of select="name"/></TD>   <TD><xsl:apply-templates select="mass"/></TD>   <TD><xsl:apply-templates select="radius"/></TD>   <TD><xsl:apply-templates select="day"/></TD>   </TR>   </xsl:template>  

In this new <planet> template, we're using <xsl:apply-templates> again to work with the child <mass> , <radius> , and <day> elements of the current <planet> element.

Note also that we're using one of the core XSLT elements here, <xsl:value-of> , to extract the value of the <name> element. (Also note that, because <planet> nodes are not direct child nodes of the root node, this new template would never match anything unless we specifically use a <xsl:apply-templates/> element in the <planets> template to invoke it on the child nodes of the <planets> node explicitly.)

Using <xsl:value-of>

The <xsl:value-of> element inserts the text value of the node you specify with the select attribute into the result document. In this case, we're assigning "name" to the select attribute, which inserts the text value of the current <planet> element's <name> element into the result document, which for us means our HTML table.

And that completes the technology we need for the remainder of this stylesheet, because all that's left to do is to create templates for each of the values we want to display and displaying those values and the value of the units attribute like this (more on the <xsl:text> element later in this chapter) :

 
 <xsl:template match="mass">     <xsl:value-of select="."/>     <xsl:text> </xsl:text>     <xsl:value-of select="@units"/> </xsl:template> <xsl:template match="radius">     <xsl:value-of select="."/>     <xsl:text> </xsl:text>     <xsl:value-of select="@units"/> </xsl:template> <xsl:template match="day">     <xsl:value-of select="."/>     <xsl:text> </xsl:text>     <xsl:value-of select="@units"/> </xsl:template> 

THE MATCH AND SELECT ATTRIBUTES

Although the <xsl:template> element uses the match attribute, <xsl:value-of> and <xsl:apply-templates> use the select attribute. We'll see that there's a significant difference here in a few pagesthe XPath expressions you can use with match are far more restricted than the ones you can use with select .


We've already seen most of how this stylesheet works, but here's something to notethe select attribute only selects the first node that matches. What if you have multiple nodes that could match? We'll take a look at that next .

Using <xsl:for-each>

For example, say you have multiple <name> elements for each planet, as you see in ch05_04.xml in Listing 5.3.

Listing 5.3 An XML Document with Multiple <name> Elements ( ch05_04.xml )
 <?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="ch05_02.xsl"?> <planets>     <planet>  <name>Mercury</name>   <name>The Hottest Planet</name>  <mass units="(Earth = 1)">.0553</mass>         <day units="days">58.65</day>         <radius units="miles">1516</radius>         <density units="(Earth = 1)">.983</density>         <distance units="million miles">43.4</distance><!--At perihelion-->     </planet>     <planet>  <name>Venus</name>   <name>Planet of Love</name>  <mass units="(Earth = 1)">.815</mass>         <day units="days">116.75</day>         <radius units="miles">3716</radius>         <density units="(Earth = 1)">.943</density>         <distance units="million miles">66.8</distance><!--At perihelion-->     </planet>     <planet>  <name>Earth</name>   <name>The Green Planet</name>  <mass units="(Earth = 1)">1</mass>         <day units="days">1</day>         <radius units="miles">2107</radius>         <density units="(Earth = 1)">1</density>         <distance units="million miles">128.4</distance><!--At perihelion-->     </planet> </planets> 

To catch all possible matches, you can use the XSLT <xsl:for-each> element as you see in ch05_05.xsl in Listing 5.4.

Listing 5.4 An Example of an XSL Stylesheet with Multiple Matches (ch05_05.xsl )
 <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">     <xsl:template match="planets">         <HTML>             <xsl:apply-templates/>         </HTML>     </xsl:template> <xsl:template match="planet">  <xsl:for-each select="name">   <P>   <xsl:value-of select="."/>   </P>   </xsl:for-each>   <BR/>  </xsl:template> </xsl:stylesheet> 

This stylesheet will catch all <name> elements, place their values in a <P> element, and add them to the output document like this:

 
 <HTML>     <P>Mercury</P>     <P>The Hottest Planet</P>     <BR>     <P>Venus</P>     <P>Planet of Love</P>     <BR>     <P>Earth</P>     <P>The Green Planet</P>     <BR> </HTML> 

As you can see, <xsl:for-each> is designed to let you handle node-sets that contain multiple nodes. At this point, then, we've been able to handle some of the XSLT basics. Two of the most important aspects are the match attribute in the <xsl:template> element and the select attribute in the <xsl:value-of> element. Much of being able to work with XSLT involves knowing what values you can assign to these attributes. You can assign XPath expressions to both of these attributes, but there are restrictions on what XPath expressions you can use with the match attribute. We'll take a look at the match attribute first, followed by the select attribute.



XPath. Navigating XML with XPath 1.0 and 2.0 Kick Start
XPath Kick Start: Navigating XML with XPath 1.0 and 2.0
ISBN: 0672324113
EAN: 2147483647
Year: 2002
Pages: 131

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net