WebReference.com - Chapter 7 of XML for ASP.NET Developers, from Sams Publishing (6/13) | WebReference

WebReference.com - Chapter 7 of XML for ASP.NET Developers, from Sams Publishing (6/13)

To page 1To page 2To page 3To page 4To page 5current pageTo page 7To page 8To page 9To page 10To page 11To page 12To page 13
[previous] [next]

XML for ASP.NET Developers

Lines 23–26:

 23:           <xsl:if test="count(//golfer) > 0">
 24:             &#xa0;
 25:             <xsl:value-of select="count(//golfer)"/>&#xa0;
 26:           </xsl:if>

This portion of the XSLT document shows how the xsl:if element can be used to test a particular condition. In this case, an XSLT function named count() is used. This function takes an XPath statement as input and returns the number of nodes as output. You'll learn more about XSLT functions in the next section.

The xsl:if element must have an attribute named test, which converts a valid XPath statement to a Boolean. In this case, the test checks to see whether the number of golfer nodes exceeds the value of 0. If the test returns true, the content (referred to as the template body) between the xsl:if start and end tags is processed.

Line 25 contains the xsl:value-of element, which is used frequently in XSLT documents to write out the value of a particular node to the result tree. This element must contain an attribute named select. The value of the attribute must contain a valid XPath expression. The node (or nodes) returned by the expression is converted to a string. In this case, the number of golfer nodes within the XML document is returned and placed in the result tree structure.

The xsl:value-of element may optionally include an attribute named disable-output-escaping that is useful when characters such as < or > need to be output without being escaped by using &lt; or &gt;. The attribute accepts a value of yes or no. Using it is especially useful when an XML element contains HTML tags that need to be written to the result tree structure without escaping the brackets.

Line 30:

30:         <xsl:apply-templates/>

The xsl:apply-templates element provides a way to call templates that may match with other items contained in the source XML document. Before explaining what this element does in more detail, it's appropriate to introduce a term called the context node. The context node is defined as the source document node currently being processed by the XSLT processor as specified by a template. Because we are processing the document node in the current template, that node is considered the context node. Obviously, many other elements are below this node, including golfers and golfer, that may also have templates associated with them. By using xsl:apply-templates the XSLT code is saying (in more human terms), "Find all templates that match with child elements of the current node (the context node) and go out and process them." The first child node that will be found is the root node of the source document (golfers). The template that matches up with it is described next.

Lines 34–36:

 34:   <xsl:template match="golfers">
 35:     <xsl:apply-templates select="golfer"/>
 36:   </xsl:template>

The golfers node in the source XML document matches up with the template defined in these lines of the XSLT document. As the XSLT processor is attempting to match templates with nodes in the XML document, any node with a name of golfers will automatically be processed by this template. Within the template, you'll notice that the content is very sparse, except for the inclusion of an xsl:apply-templates element. With the context node now being the golfers node, calling xsl:apply-templates will send the processor looking for templates that match up with child nodes of the golfers node.

You'll notice that line 30 includes an attribute named select that applies to the xsl:apply-templates element. This attribute accepts a valid XPath expression as a value. In this case, it selects a template that matches up with a node named golfer. Because the golfers node contains golfer nodes only as children, including this attribute is unnecessary and is shown only to exemplify its use. If, however, the golfers node contained child nodes other than the golfer node and we wanted the golfer node template to be processed first, the inclusion of the select attribute would be more appropriate. This will become more clear as the next template is discussed.

Lines 37–99:

 37:   <xsl:template match="golfer">
 38:     <table class="borders" border="0" width="640"
 39:      cellpadding="4" cellspacing="0" bgcolor="#efefef">
 40:       <xsl:apply-templates select="name"/>
 41:       <tr class="blackText">
 42:         <td width="12%" align="left">
 43:           <b>Skill: </b>
 44:         </td>
 45:         <td width="12%" align="left">
 46:           <xsl:attribute name="style">
 47:             <xsl:choose>
 48:               <xsl:when test="@skill='excellent'">
 49:                 color:#ff0000;font-weight:bold;
 50:               </xsl:when>
 51:               <xsl:when test="@skill='moderate'">
 52:                 color:#005300;
 53:               </xsl:when>
 54:               <xsl:when test="@skill='poor'">
 55:                 color:#000000;
 56:               </xsl:when>
 57:               <xsl:otherwise>
 58:                 color:#000000;
 59:               </xsl:otherwise>
 60:             </xsl:choose>
 61:           </xsl:attribute>
 62:           <xsl:value-of select="@skill"/>
 63:         </td>
 64:         <td width="12%" align="left">
 65:           <b>Handicap: </b>
 66:         </td>
 67:         <td width="12%" align="left">
 68:           <xsl:value-of select="@handicap"/>
 69:         </td>
 70:         <td width="12%" align="left">
 71:           <b>Clubs: </b>
 72:         </td>
 73:         <td width="40%" align="left">
 74:           <xsl:value-of select="@clubs"/>
 75:         </td>
 76:       </tr>
 77:       <tr>
 78:         <td colspan="6">&#xa0;</td>
 79:       </tr>
 80:       <tr class="blackText">
 81:         <td colspan="6" class="largeBlackText">
 82:           Favorite Courses 
 83:         </td>
 84:       </tr>
 85:       <tr>
 86:         <td colspan="2">
 87:           <b>City: </b>
 88:         </td>
 89:         <td colspan="2">
 90:           <b>State: </b>
 91:         </td>
 92:         <td colspan="2">
 93:           <b>Course: </b>
 94:         </td>
 95:       </tr>
 96:       <xsl:apply-templates select="favoriteCourses"/>
 97:     </table>
 98:     <p/>
 99:   </xsl:template>

This template does the bulk of the work in Listing 7.4 by matching up with all golfer nodes in the source XML document. When the template is processed, the shell structure for an HTML table is written out. This table will be used to present all the information about a specific golfer. Line 40 uses the xsl:apply-templates and provides a pattern for the template that should be called by using the select attribute. By providing a pattern equal to name, only a template that matches up with the pattern will be processed. Why didn't we simply call xsl:apply-templates and not worry about which of the context node's child node templates were called? The answer is that we want to ensure that the template with a pattern matching the name child node is processed before any other children of the context node (golfer, in this case).

After the template matching the name node is called, processing will be done on that template and then return to the golfers template. Specifically, the XSLT processor will jump back to the next statement in the golfer template that immediately follows the call to <xsl:apply-templates select="name"/>.

Lines 46–74 exhibit several of the XSLT elements shown earlier in Table 7.1. To start things off, line 46 contains an xsl:attribute element named style. This XSLT element adds a style attribute to the <td> tag in line 45. The value of the attribute is dynamically assigned based on a series of conditional tests. To accomplish the tests, the xsl:choose, xsl:when, and xsl: otherwise elements are used. These elements function in a manner similar to the switch, case, and default keywords used when coding a switch statement in C#.

The conditional test starts with the xsl:choose element. It can be followed by as many xsl:when elements, as needed. The xsl:when element must contain a mandatory attribute named test that contains the expression to test. If the test returns true, the content between the xsl:when starting and ending tags will be assigned to the value of the style attribute. The test performed in line 48 checks to see whether an attribute of the context node (remember that the context node is golfer at this point) named skill has a value equal to excellent. If it does, the style attribute will have a value of color:#ff0000;font-weight:bold;. Assuming the skill attribute does have a value of excellent, the actual structure added on completion of the xsl:choose block testing will be the following:

<td width="12%" align="left" style="color:#ff0000;font-weight:bold;">

If the first xsl:when returns false, testing will continue down the line. If no xsl:when tests return true, the xsl:otherwise block will be hit and the style attribute will be assigned a value of color:#000000; (lines 57–59).

After the style attribute has been added to the <td> tag, processing continues with line 62, which adds the value of the skill attribute to the table column by using the xsl:value-of element discussed earlier. Lines 64–94 continue to add additional columns to the table and write out the value of attributes found on the context node (the golfer node).

When processing in the golfers template completes, the xsl:apply-templates element is again used along with a select attribute that points to a template pattern of favoriteCourses (line 96). This template will be discussed later.

Lines 100–107:

100:   <xsl:template match="name">
101:     <tr>
102:       <td colspan="6" class="largeYellowText" bgcolor="#02027a">
103:         <xsl:value-of select="firstName"/>&#xa0;
104:         <xsl:value-of select="lastName"/>
105:       </td>
106:     </tr>
107:   </xsl:template>

The template declaration shown in line 100 matches up with all name nodes found within the XML document. This template is called from within the golfer template discussed earlier (see line 40). Processing of the template is limited to writing out a new row in the table (line 101) followed by a column containing the values of the firstName and lastName elements. These values are written to the result tree by using the xsl:value-of element(lines 103 and 104).

Lines 108–127:

108:   <xsl:template match="favoriteCourses">
109:     <xsl:apply-templates/>
110:   </xsl:template>
111:   <xsl:template match="course">
112:     <xsl:call-template name="writeComment"/>
113:     <tr class="blackText">
114:       <td colspan="2" align="left">
115:         <xsl:value-of select="@city"/>
116:       </td>
117:       <td colspan="2" align="left">
118:         <xsl:value-of select="@state"/>
119:       </td>
120:       <td colspan="2" align="left">
121:         <xsl:value-of select="@name"/>
122:       </td>
123:     </tr>
124:   </xsl:template>
125:   <xsl:template name="writeComment">
126:     <xsl:comment>List Course Information</xsl:comment>
127:   </xsl:template>

The template matching favoriteCourses contains no functionality other than to call xsl: apply-templates. This is because it contains no attributes and acts only as a parent container element. Because the favoriteCourses node contains only child nodes named course, calling xsl:apply-templates will result in only one template match.

Processing within the template that matches the course nodes is limited to adding a new row (line 113) with columns containing the values for attributes named city, state, and name. Each course node found within the source XML document will be matched with this template and the appropriate attribute values will be written out.

Line 112 introduces a new XSLT element that hasn't been covered to this point. The xsl:call-template element can be used to call a template in a similar manner as calling a function within C# or VB.NET. Calling a template in XSLT is accomplished by identifying the name of the template to call via a name attribute. The template that is called must, in turn, have a matching name attribute as shown in line 125.

Calling templates can be useful when a template doesn't match up with a given node in an XML document but needs to be accessible to process commonly used features or perform calculations. For example, if your XSLT code needs to walk through a list of pipe-delimited strings, a template can be called recursively until each piece of data within the string has been processed. You'll see a concrete example of using the xsl:call-template element in conjunction with the xsl:with-param and xsl:param elements toward the end of this chapter.

Line 128:

128: </xsl:stylesheet>

The XSLT language follows all the rules outlined in the XML specification. As such, the xsl:stylesheet element must be closed.

This example has shown how you can use some of the main elements found in the XSLT specification. For more information on some of the other elements not covered in the previous example, refer to the XSLT version 1.0 specification (http://www.w3.org/TR/1999/REC- xslt-19991116) or pick up a copy of a book titled XSLT Programmer's Reference (ISBN 1-861003-12-9).

To page 1To page 2To page 3To page 4To page 5current pageTo page 7To page 8To page 9To page 10To page 11To page 12To page 13
[previous] [next]

© Copyright Pearson Education and Created: April 22, 2002
Revised: April 22, 2002

URL: http://webreference.com/authoring/languages/xml/aspnet/chap7/6.html