XSLT Operation

[Previous] [Next]

XSLT is a rules-based, event-driven programming language. It is not a procedural language. Think of XSLT as a clerk who's in charge of a room filled with boxes. Each box does something useful. Figure 6-2 shows a template rule—which is a stand-alone object—waiting for an event defined by the match attribute. Once the rule receives an event, the rule can expose the content to other rules (apply-templates) or can output directly (value-of).

When an element comes along, the clerk selects a box based on certain criteria (usually events happening in the XML input document) and drops the result of those events into the box. Figure 6-3 illustrates this step.

click to view at full size.

Figure 6-2. An XML template rule encapsulates processing details, allowing the programmer to focus on input and output.

click to view at full size.

Figure 6-3. XSLT is analogous to a set of boxes that do mysterious processing inside. Depending on the processing, a box might output something for other boxes to process, something that is directly sent to the output, or nothing at all. Table 6-1 describes this processing in detail.

The processing happens in a box. Most of the time something comes out of that box. Depending on what the box does, this output might be static text, the result of calculations, or an element structure. The result that comes out will either go directly to the output or will be exposed to other boxes, which will process it further. I will show later how this process is done using the XSL transformation engine. In the following example, I'll walk you through the processing illustrated in Figure 6-3 with the simple XML document Curcon.xml:

 <?xml version="1.0"?> <weather type="Current conditions"> <temp>76</temp> <wind>5</wind> </weather> 

I'll also use the XSL style sheet Weathersheet.xsl, shown in Listing 6-1.

Listing 6-1. Weathersheet.xsl, an XSL style sheet that formats weather data.

 

Weathersheet.xsl

1 <?xml version="1.0"?> 2 <xsl:stylesheet 3 version="1.0" 4 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 5 6 <xsl:template match="weather"> 7 <H1><xsl:value-of select="@type"/></H1> 8 <xsl:apply-templates/> 9 <HR/> 10 </xsl:template> 11 12 <xsl:template match="temp"> 13 <LI>Temperature <xsl:apply-templates/>&#x00B0;F</LI> 14 </xsl:template> 15 16 <xsl:template match="wind"> 17 <LI>Wind <xsl:apply-templates/>mph</LI> 18 </xsl:template> 19 20 <xsl:template match="text()"> 21 <xsl:value-of select="."/> 22 </xsl:template> 23 24 </xsl:stylesheet>

Table 6-1 describes the processing illustrated in Figure 6-3. You'll find the corresponding line numbers from Listing 6-1 in the description section of the table. Read through the description and see how each step is implemented in code.

Table 6-1. A step-by-step breakdown of the XSLT processing illustrated in Figure 6-3.

Step in Figure Description
1 One of the boxes is designed to process the weather element in the XML document. Since the weather element is the root element, the weather element and all of its descendants (an important fact to remember) are stuffed into the box. This box, with a square hole (as shown in Figure 6-3), is defined in the template rule on lines 6-10.
2 The first thing the box produces is some output. Using the <xsl:value-of/> element creates the text contents of the object in the select attribute. In this case, the content of the type attribute (@type) are sent out inside an HTML <H1> element. The XSL processor processes any element with the xsl: namespace prefix. Anything without the xsl: namespace prefix is sent verbatim to the output. The next command, <xsl:apply-templates/>, spits out the content of the weather element so that other boxes in the room can process it.
3 The first item contained inside weather is <temp>76</temp>. This is an element, and a box is waiting to process it—the one with a diamond-shaped hole. This box maps to the template rule on lines 12-14.
4 The HTML list item (<LI>) element start tag and the literal text "Temperature" do not have the xsl: namespace prefix, so they are sent directly to the output.
5 Now the box notices the <xsl:apply-templates/> element and, as with the weather element, spits out the content of the temp element, "76". This content can now be processed by another box.
6 The box with a donut hole is waiting. This box processes all text exposed by the other boxes. It is the template rule on lines 20-22. The single <xsl:value-of/> element will send the textual content of the thing that was captured (which can only be a textual element) directly to the output, which is indicated by the round hole in the front of the box.
7 After the text is processed, control returns to the "temp" rule, which outputs the end tag for the list item element. Once the temperature element has been processed, control reverts back to the weather template rule, where it waits to process the next child.
8-12 The wind element is that child, so the weather box spits out the wind element just like it spat out the temperature element, exposing the element to the boxes in the room.
13 After all children of the weather element have been processed, the <xsl:apply-templates/> element is finished and the rule continues to process the commands following it. In this case, there is a single HTML horizontal rule tag. It is sent to the output and processing terminates.

Notice the syntax of the HTML horizontal rule tag in line 9. Remember that an XSL style sheet is a well-formed XML document. That means that it must adhere to the well-formedness constraints described in Chapter 4. Normally, the tag looks like this: <HR>. However, the horizontal rule tag is an empty element. Since the horizontal rule tag is included in line with the other XSL elements, it must also be well-formed, so it takes a slightly different form: <HR/>.

Recursive Processing

It is important to note that when a box spits out the content of an element for which it finds a match, the content is exposed to all the template rules, including the rule that created it. I'll demonstrate this with the short XSL program Generic.xsl, shown in Listing 6-2.

Listing 6-2. Generic.xsl, an XSL style sheet for generically processing any XML document to create a hierarchical view.

 

Generic.xsl

1 <?xml version="1.0" ?> 2 <xsl:stylesheet 3 version="1.0" 4 xml:space="default" 5 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 6 7 <xsl:template match="node()"> 8 <DIV STYLE="margin-left:12pt;"> 9 [start <xsl:value-of select="name()"/>] 10 <xsl:apply-templates select="@*"/> 11 <xsl:apply-templates/> 12 [end <xsl:value-of select="name()"/>] 13 </DIV> 14 </xsl:template> 15 16 <xsl:template match="@*"> 17 [attr <xsl:value-of select="name()"/>: 18 <xsl:value-of select="."/>] 19 </xsl:template> 20 21 <xsl:template match="text()"> 22 <xsl:value-of select="."/> 23 </xsl:template> 24 25 </xsl:stylesheet>

Notice that the style sheet in Listing 6-2 has no hard-coded element or attribute names. All elements are processed anonymously, according to their position in the document. We'll need ways to find out the names and types of each node that comes along, so we must build those capabilities into our style sheet that processes the document. Listing 6-3 shows the XML document 80112.xml, which I'm going to process.

Listing 6-3. 80112.xml, an XML document for our generic processing example.

 

80112.xml

<weather zipcode="80112"> <location>Englewood, CO </location> <current> <condition name="temp">32</condition> <condition name="wind chill">20</condition> <condition name="wind">from the South at 7 mph</condition> <condition name="dewpoint">16 </condition> <condition name="relative humidity">51%</condition> <condition name="visibility">10 miles</condition> <condition name="barometer">30.01 inches</condition> <condition name="sunrise">7:20 am MST</condition> <condition name="sunset">4:51 pm MST</condition> </current> <forecast updated="2000-03-21T15:03:27-07:00"> <day date="2000-03-22T15:03:28-07:00" high="46" low="21" sky="Partly Cloudy"/> <day date="2000-03-23T15:03:28-07:00" high="51" low="25" sky="Partly Cloudy"/> <day date="2000-03-24T15:03:28-07:00" high="51" low="19" sky="Partly Cloudy"/> <day date="2000-03-25T15:03:28-07:00" high="53" low="21" sky="Partly Cloudy"/> <day date="2000-03-26T15:03:28-07:00" high="49" low="20" sky="Partly Cloudy"/> </forecast> </weather>

Table 6-2 gives you a play-by-play of what happens when the style sheet in Listing 6-2 processes the XML document in Listing 6-3.

Table 6-2. A line-by-line breakdown describing the XSLT processing of the file 80122.xml using the Generic.xsl stylesheet.

Line Description
7 The match="node()" rule will match just about any node that comes along. We are mostly interested in processing the element nodes, so node is a good choice.
8 The first line of the match rule (line 8) has an HTML <DIV> element. A <DIV> is a breaking container that we can use to hold each element. Notice that <DIV> does not have an xsl: namespace declaration, so the <DIV> element will be sent directly to the output, along with its attributes. The STYLE attribute is an inline CSS style indicating the left margin of the <DIV>.
9 The literal string [start does not have the xsl: namespace prefix, so it is sent to the output. Then the name of the element is output. By using the name node text inside the select attribute of the <xsl:value-of/> element, we are asking the node for its name—just as we ask it for its value when we use select=".". A literal ] follows the name of the element.

The resulting output from this line takes the following form:

 [start weather] 

10 Until now, we have used only the <xsl:apply-templates/> element used by itself. Notice the select attribute on the apply-templates element. By default, the select attribute will select all nodes and expose them to all the templates in the style sheet. However, if we change the select attribute, we can restrict the kinds of nodes that we process. In this example, we want to process only attribute nodes. The pattern for selecting all attributes is "@*".
16 Since our first element has an attribute (zipcode), this template rule in this line will catch it.
17-18

The select="name()" node test returns the name of the attribute that was matched by the parser. In this template, an attribute was matched, so name returns the name of the attribute. The value of the attribute is processed the same way as the text value of an element node.

The resulting output from this line takes the following form:

 [attr zipcode: 80112] 

11 When the attributes finish processing, control returns to the line following the apply-templates element that exposed the attributes (line 11). This line is the unqualified apply-templates element, which will expose all the element children to all the template rules.
7 Surprise! The first element in the <weather> element is <location>. The same rule that caught the root element <weather> will catch and process the <location> element also.
8 Just as with the parent element, a <DIV> is generated with a cascading style of a 12-point left indent. Remember that when the <weather> element was processed, a 12-point left-indenting <DIV> appeared, but that <DIV> was not yet closed. The <DIV> for our <location> element is inside the <weather> <DIV>. One nice feature of cascading style sheets is (of course) that they cascade, which in this case means that everything inside the <location> element is indented 12 more points, to result in a 24-point indent.
11 The content of the <location> element is processed on this line. A single text node is inside of this element, and that text node is caught by the rule that matches text in line 21.
21 In the same way that the node test matches any element node, the text node test captures any contiguous string of text.
22 The value of the text captured is output to the browser. Control returns to line 11, where parsing continues.
12 After the content of each element is processed, we want to indicate some kind of ending notification. This line will output the name of the element that is currently being processed inside square brackets.
13 The closing </DIV> tag marks the end of this 12-point indent. The indent level reverts back to where it was before the element was processed.
7-14 This template rule will be called recursively (meaning it calls itself) for each element in the XML file until the entire document is processed.

When we pop the resulting HTML output into our favorite Web browser, we can see that there is a nested representation of the information, as shown in Figure 6-4. The file in Figure 6-4 was created by using the transformNode() method of the Microsoft XML DOM implementation. We will see several different ways to use this method later.

click to view at full size.

Figure 6-4. A nested view of an XML document processed with the generic style sheet.

XSLT by Example

Let's try some other XSLT elements. Keep in mind the recursive nature symbolized by the room full of boxes. Consider the XML document Duckone.xml in Listing 6-4.

Listing 6-4. The Duckone.xml XML document used in the XSLT demonstration.

Duckone.xml

<?xml version="1.0"?> <?xml-stylesheet type="text/xsl" href="joke.xsl"?> <Jokes xml:space="default"> <Joke type="one-liner" author="Brian">A duck walks into a bar and says,<quote>Gimme a beer and put it on my bill</quote>. </Joke> <Joke type="story" author="Monty"> <Scene num="1">My dog has no nose</Scene> <Scene num="2">How does he smell?</Scene> <Scene num="3">Terrible!</Scene> </Joke> <Joke type="knock-knock" author="Miller"> <Line>Knock-knock</Line> <Line>Who's there?</Line> <Line>Boo</Line> <Line>Boo who?</Line> <Line>It's just a joke, you don't have to cry about it.</Line> </Joke> </Jokes>

This document contains three elements named Joke. Each has a different value for the type attribute. Rules in the XSLT document Joke.xsl will individually process each element. Listing 6-5 contains the XSLT style sheet for this example.

Listing 6-5. The XSL style sheet Joke.xsl transforms an XML document for HTML output in the browser.

 

Joke.xsl

1 <?xml version="1.0"?> 2 <xsl:stylesheet 3 version="1.0" 4 xmlns:msxsl="urn:schemas-microsoft-com:xslt" 5 xmlns:scripts="http://architag.com/scripts" 6 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 7 8 <xsl:output method="html" version="4.0"/> 9 10 <msxsl:script implements-prefix="scripts"> 11 <![CDATA[ 12 function showXML(nodelist) 13 { 14 txtResult = "<SPAN "+ 15 "STYLE='background-color:lightyellow;" + 16 "cursor:hand;font-size:8pt;' " + 17 "TITLE='" 18 replaceText = nodelist.nextNode().xml 19 replaceText = replaceText.replace(/&/g, '&amp;') 20 replaceText = replaceText.replace(/</g, '&lt;') 21 replaceText = replaceText.replace(/>/g, '&gt;') 22 replaceText = replaceText.replace(/'/g, '&rsquo;') 23 txtResult += replaceText 24 txtResult += "'>(show xml)</SPAN>" 25 return txtResult; 26 } 27 ]]> 28 </msxsl:script> 29 30 <xsl:template match="Jokes"> 31 <HTML> 32 <HEAD> 33 <TITLE>XSL Demonstration</TITLE> 34 <STYLE> 35 P, UL {margin-top:2pt;margin-bottom;2pt;} 36 H1, H2, H4 {margin-top:2pt;margin-bottom;2pt;} 37 </STYLE> 38 </HEAD> 39 <BODY STYLE="font-family:Verdana;"> 40 <xsl:value-of select="scripts:showXML(.)" 41 disable-output-escaping="yes"/> 42 <H1>World's Funniest Jokes</H1> 43 <DIV STYLE= 44 "border:1px solid black;padding:3pt;"> 45 <H4>Table of Contents</H4> 46 <xsl:for-each select="Joke"> 47 <A> 48 <xsl:attribute 49 name="HREF">#<xsl:value-of 50 select="generate-id()"/> 51 </xsl:attribute> 52 <xsl:value-of select="@type"/> 53 </A><BR/> 54 </xsl:for-each> 55 </DIV> 56 <xsl:apply-templates/> 57 </BODY> 58 </HTML> 59 60 </xsl:template> 61 <xsl:template name="email-author"> 62 <xsl:param name="author-alias"/> 63 Author: <xsl:element name="A"> 64 <xsl:attribute 65 name="HREF">mailto:<xsl:value-of 66 select="$author-alias"/>@jokes.architag.com 67 </xsl:attribute> 68 <xsl:value-of select="$author-alias"/> 69 </xsl:element><BR/> 70 </xsl:template> 71 72 <xsl:template name="set-name"> 73 <A> 74 <xsl:attribute name="NAME"> 75 <xsl:value-of select="generate-id()"/> 76 </xsl:attribute> 77 </A> 78 </xsl:template> 79 80 <xsl:template match="Joke[@type='story']"> 81 <xsl:call-template name="set-name"/> 82 <H2>Story Joke 83 <xsl:value-of select="scripts:showXML(.)" 84 disable-output-escaping="yes"/> 85 </H2> 86 <xsl:call-template name="email-author"> 87 <xsl:with-param name="author-alias"> 88 <xsl:value-of select="@author"/> 89 </xsl:with-param> 90 </xsl:call-template> 91 <P> 92 <xsl:for-each select="Scene"> 93 <B>Scene <xsl:value-of select="@num"/>: </B> 94 <xsl:value-of select="."/><BR/> 95 </xsl:for-each> 96 <I><xsl:value-of select="$laughtrack"/></I></P> 97 </xsl:template> 98 <xsl:template match="Joke[@type='knock-knock']"> 99 <xsl:call-template name="set-name"/> 100 <H2>Knock-knock 101 <xsl:value-of select="scripts:showXML(.)" 102 disable-output-escaping="yes" /> 103 </H2> 104 <xsl:call-template name="email-author"> 105 <xsl:with-param name="author-alias"> 106 <xsl:value-of select="@author"/> 107 </xsl:with-param> 108 </xsl:call-template> 109 <UL> 110 <xsl:apply-templates/> 111 </UL> 112 <I><xsl:value-of select="$laughtrack"/></I> 113 </xsl:template> 114 115 <xsl:template match="Joke[@type='one-liner']"> 116 <xsl:call-template name="set-name"/> 117 <H2>One-liner 118 <xsl:value-of select="scripts:showXML(.)" 119 disable-output-escaping="yes"/> 120 </H2> 121 <xsl:call-template name="email-author"> 123 <xsl:with-param name="author-alias"> 124 <xsl:value-of select="@author"/> 125 </xsl:with-param> 126 </xsl:call-template> 127 <P><xsl:apply-templates/><BR/> 128 <I><xsl:value-of select="$laughtrack"/></I></P> 129 </xsl:template> 130 131 <xsl:template match="Joke[@type='knock-knock']/Line"> 132 <LI><xsl:apply-templates/></LI> 133 </xsl:template> 134 135 <xsl:template match="quote"> 136 "<xsl:apply-templates/>" 137 </xsl:template> 138 139 <xsl:variable name="laughtrack">(laugh track)</xsl:variable> 140 141 </xsl:stylesheet>

Table 6-3 provides a line-by-line description of the transformation implemented in the Joke.xml file in Listing 6-4.

Table 6-3. A line-by-line description of the transformation defined by the XSLT Joke.xsl.

Line Description
4-6 This XSLT program requires three namespaces. The first namespace contains Microsoft extensions to the XSLT language. The next namespace is required by the script element, as you'll see later. The XSLT processor requires the third namespace to know which version of XSLT to use. In this case, the processor will use the final XSLT Recommendation approved by the W3C in November 1999.
8 The xsl:output element declares the type of output desired. In this case, we want the output to adhere to the HTML version 4.0 specification.
10-28 This block of code is an example of script. The XSLT specification does not include a built-in scripting interface. Each implementer of the spec is responsible for designing a script interface if one is required. The Microsoft implementation offers a number of scripting options. In this case we're using Microsoft JScript.

We'll use this script to create a string of HTML that represents the structure of an XML node.

30-59 When the XML document is loaded, the XML parser reads the document into the document object model tree and starts navigating the tree from the root. The root element, Jokes, will be processed first, and then the rest is processed. The first template matched will be for the first event generated. In this case, the template is the root element, Jokes. This rule defines the structure of the HTML document, including a CSS element.
40 The xsl:value-of element can call on a script defined by the XSLT implementation. In this case, the ShowXML function defined in line 12 is called, causing the text "Show XML" to be put inside of a span, with the contents of the current element (the argument, ".", passed to the function) put in the TITLE attribute. The net result is to create a string of text that has other text "behind" it—that is, when the user hovers the mouse pointer over the text "Show XML", the actual text of the element appears in a yellow pop-up window.
41 By default, the value-of element escapes the content it processes, meaning that all markup characters turn into their entity reference equivalents. For example, if a left angle bracket (<) is encountered, it is replaced with the entity reference for a left angle bracket, &lt;. This replacement protects the XML output from interpreting literal characters in the text as markup.

In our example, we don't want to use this kind of escaping, so we use the disable-output-escaping attribute to override the default behavior.

45-54 This section generates a table of contents based on the content of the document.
46 The xsl:for-each element establishes a collection of elements according to the select attribute. In this case, it will create a three-member collection of Joke element nodes. These members are processed by the content of the xsl:for-each element one member at a time.
47-53 In this section, the HTML A element encloses each item.
48 The xsl:attribute element adds an element to the currently open element. In this case, the element is A. The HREF attribute will be added with a value of a hash mark (#) and…
49 …the unique identifier of the member of the collection. The Microsoft XML parser assigns a locally unique identifier to each element in the document. You can access this unique identifier with the generate-id function.
52 The value of the type attribute on the Joke element is processed here. This value will be listed inside the <A> tag.
53 Notice the strange form of the HTML break tag (<BR/>). Remember that an XSLT style sheet is a well-formed XML document and thus must adhere to a number of well-formedness constraints defined by the XML spec. The HTML break tag, <BR>, is an empty element, and the HTML processor will interpret it properly if it looks like a normal start tag. However, because we are creating well-formed HTML, empty elements have a special form. In this case, the break tag appears as <BR/>.
56 The content of the node captured by the template element in the match attribute are exposed to all of the templates in the style sheet by this xsl:apply-templates element. This element will force document processing at this point.
57-58 Once the children are processed, the HTML BODY and HTML tags are closed.
61-70 Until this point, we have seen templates that sit around until an event in the input fires them. You can also create templates that act as subroutines that are called by other templates.

Notice that this particular template does not have a match attribute. This kind of template is called a named template; it will be called by name from somewhere else. Named templates are similar to subroutines in any other language: you use named templates when you have a certain amount of processing to do and you don't want to repeat code in all the places that require the processing.

62 Named templates can interpret parameters passed from the calling rule. In this case, a parameter called author-alias is passed.
66 The author-alias parameter is put inside the HREF attribute of the HTML A element.
68 The author-alias value is repeated in this section.
72-78 The template set-name is another named template, but it does not require a parameter. This template will be called from somewhere else, and the required values are calculated internally within the template rather than being passed from an external call.
80 This template matches a joke, but only if it has an attribute named type that has a value of story. The string adheres to the XPath abbreviated form.
81 The named template on lines 72-78 is called here, causing any output produced by the named template to be output at this point.
83 Again, the showXML function is called, passing the content of the current element ".".
86-90 We invoke named templates with the xsl:call-template element. This element calls the email-author named template and passes the author-alias parameter equal to the value of the author attribute of the Joke element.
92-95 This particular type of Joke (type='story') contains a number of scenes, which the xsl:for-each element processes in order.
93 The literal text "Scene" is followed by the value of the number attribute and appears in bold.
94 The xsl:value-of element outputs the text content of the scene by using the select="." attribute, followed by a well-formed HTML break tag.
139 XSLT allows you to assign variable names to constant values. The xsl:variable element sets the value of the laughtrack variable.
96 The xsl:value-of element can output the content of predefined variables. In this case, the value of the laughtrack variable is output in italics following the story.
99 The next type of joke, knock-knock, is processed here. The processing is similar to the story joke.
116 The processing that occurred with the previous jokes occurs with a one-liner joke.
131-133 A knock-knock joke contains a number of lines—a structure similar to that of the story joke. In the story joke, however, we used the xsl:for-each structure to process the children. For knock-knock jokes, the content of the joke is processed on line 111. At that point, the template on line 131 is called.
131 Notice the match attribute. This returns a Line element, but only if the Line element is a direct child (indicated by the / separator) of a Joke element, and only if the Joke element has an attribute type with a value of knock-knock. As you can see, XPath patterns can get pretty detailed.
135-137 This section contains one last template to process quotes inside literal quotation marks.

Transforming the XML document in Listing 6-4 with the XSL document in Listing 6-5 results in the HTML in Listing 6-6.

Listing 6-6. HTML output from the transformation of XML in Listing 6-4 with XSL in Listing 6-5.

 

Joketrans.htm

<HTML> <HEAD> <META http-equiv="Content-Type" content="text/html; charset=UTF-16"> <TITLE>XSL Demonstration</TITLE> <STYLE> P, UL {margin-top:2pt;margin-bottom;2pt;} H1, H2, H4 {margin-top:2pt;margin-bottom;2pt;} </STYLE> </HEAD> <BODY STYLE="font-family:Verdana;"> <SPAN STYLE='background-color:lightyellow;cursor:hand; font-size:8pt;' TITLE='&lt;Jokes xml:space="default"&gt; &lt;Joke type="one-liner" author="Brian"&gt;A duck walks into a bar and says,&lt;quote&gt;Gimme a beer and put it on my bill&lt;/quote&gt;. &lt;/Joke&gt; &lt;Joke type="story" author="Monty"&gt; &lt;Scene num="1"&gt;My dog has no nose&lt;/Scene&gt; &lt;Scene num="2"&gt;How does he smell?&lt;/Scene&gt; &lt;Scene num="3"&gt;Terrible!&lt;/Scene&gt; &lt;/Joke&gt; &lt;Joke type="knock-knock" author="Miller"&gt; &lt;Line&gt;Knock-knock&lt;/Line&gt; &lt;Line&gt;Who&rsquo;s there?&lt;/Line&gt; &lt;Line&gt;Boo&lt;/Line&gt; &lt;Line&gt;Boo who?&lt;/Line&gt; &lt;Line&gt;It&rsquo;s just a joke, you don&rsquo;t have to cry about it.&lt;/Line&gt; &lt;/Joke&gt; &lt;/Jokes&gt;'>(show xml)</SPAN> <H1>World's Funniest Jokes</H1> <DIV STYLE="border:1px solid black;padding:3pt;"> <H4>Table of Contents</H4> <A HREF="#ID0JNN2">one-liner</A><BR> <A HREF="#IDwONN2">story</A><BR> <A HREF="#ID0VNN2">knock-knock</A><BR> </DIV> <A NAME="ID0JNN2"/> <H2>One-liner <SPAN STYLE='background-color:lightyellow;cursor: hand;font-size:8pt;' TITLE='&lt;Joke type="one-liner" author="Brian"&gt;A duck walks into a bar and says,&lt;quote&gt;Gimme a beer and put it on my bill&lt;/quote&gt;. &lt;/Joke&gt;'>(show xml)</SPAN></H2> Author: <A HREF="mailto:Brian@jokes.architag.com">Brian</A><BR> <P>A duck walks into a bar and says, "Gimme a beer and put it on my bill" . <BR><I>(laugh track)</I></P> <A NAME="IDwONN2"/> <H2>Story Joke <SPAN STYLE='background-color:lightyellow; cursor:hand;font-size:8pt;' TITLE='&lt;Joke type="story" author="Monty"&gt; &lt;Scene num="1"&gt;My dog has no nose&lt;/Scene&gt; &lt;Scene num="2"&gt;How does he smell?&lt;/Scene&gt; &lt;Scene num="3"&gt;Terrible!&lt;/Scene&gt; &lt;/Joke&gt;'>(show xml)</SPAN></H2> Author: <A HREF="mailto:Monty@jokes.architag.com">Monty</A><BR> <P> <B>Scene 1: </B>My dog has no nose<BR><B>Scene 2: </B> How does he smell?<BR><B>Scene 3: </B>Terrible!<BR> <I>(laugh track)</I></P> <A NAME="ID0VNN2"/> <H2>Knock-knock <SPAN STYLE='background-color:lightyellow;cursor:hand; font-size:8pt;' TITLE='&lt;Joke type="knock-knock" author="Miller"&gt; &lt;Line&gt;Knock-knock&lt;/Line&gt; &lt;Line&gt;Who&rsquo;s there?&lt;/Line&gt; &lt;Line&gt;Boo&lt;/Line&gt; &lt;Line&gt;Boo who?&lt;/Line&gt; &lt;Line&gt;It&rsquo;s just a joke, you don&rsquo;t have to cry about it.&lt;/Line&gt; &lt;/Joke&gt;'>(show xml)</SPAN></H2> Author: <A HREF="mailto:Miller@jokes.architag.com">Miller</A><BR> <UL> <LI>Knock-knock</LI> <LI>Who's there?</LI> <LI>Boo</LI> <LI>Boo who?</LI> <LI>It's just a joke, you don't have to cry about it.</LI> </UL> <I>(laugh track)</I> </BODY> </HTML>

Figure 6-5 shows the HTML output produced by the transformation. This output was created using the XSL transformation engine in XRay. The workspace is available on the companion CD at \Samples\Ch06\Chapter6.xrw. This will load the XML document, the XSL stylesheet, the transformation window, and an HTML browser window. We will use XRay to do this in the next section.

click to view at full size.

Figure 6-5. The resulting output of Listing 6-6, as seen in a Web browser. This figure shows both the XML document and the XSL style sheet in XRay, along with the resulting HTML and an example in the browser window. This example shows a pop-up window containing the source XML document, as contained in the TITLE attribute of the HTML SPAN element.



XML and SOAP Programming for BizTalk Servers
XML and SOAP Programming for BizTalk(TM) Servers (DV-MPS Programming)
ISBN: 0735611262
EAN: 2147483647
Year: 2000
Pages: 150

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