Common Action Instructions

 
xslt for dummies
Chapter 4 - Templates Rule!
XSLT For Dummies
by Richard Wagner
Hungry Minds 2002
  

Within a template rules template, a few key XSLT instructions do the yeomans work of generating nodes for the result documents. These action instructions you use most often are xsl:apply-templates , xsl:copy , xsl:copy-of , and xsl:value-of .

 Tip   In XSLTSpeak, top-level XSLT elements, such as xsl:template or xsl:output are called elements, whereas XSLT elements in the template rule that are used to create part of the result tree are called instructions .

xsl:apply-templates

The xsl:apply-templates element is perhaps the most commonly used instruction inside template rules. Its most basic syntax is:

 <xsl:apply-templates  select="expression"  /> 

The select attribute (shown in italic) is purely optional.

 Tip   Think of xsl:apply-templates as something like a stereotypical factory supervisor. It doesnt really do anything by itself, but is charged with telling others, "Hey you, do this."

The purpose of xsl:apply-templates is to invoke the template rule most appropriate for the current node and its children. It doesnt really do anything by itself, but tells another template rule to do something. In some cases, the template rule called upon is the one that contains the xsl:apply-templates instruction. In other cases, it may be another template rule defined in your stylesheet. And, if nothing else is found, the XSLT processor applies one of XSLTs built-in template rules. (I discuss built-in template rules later in the chapter.)

Two obvious questions follow: How does xsl:apply-templates know which nodes to process? And after a node or node set is selected for processing, how does xsl:apply-templates decide which template rule to apply? I discuss the answers to these questions in the next two sections.

Scope of xsl:apply-templates

The xsl:apply-templates instruction processes nodes within its context or scope. When its select attribute is not defined, then its scope is the node set returned from the match pattern of the template rule it is inside of. For example, in the code snippet below, xsl:apply-templates processes the tv element and its children from the XML file shown in Listing 4-2:

 <xsl:template match="tv"> <xsl:apply-templates> </xsl:template> 

For each node in the node set, its template rule is applied along with all of its childrens template rules.

Or, if select is defined, only the nodes that result from the expression are transformed, along with their children. For example, when the following template rule is processed on the tv.xml file in Listing 4-2, only the aspectratio element is applied by xsl:apply-templates , the tv , model , and type elements are ignored by this xsl:apply-templates instruction:

 <xsl:template match="tv"> <xsl:apply-templates select="aspectratio"> </xsl:template> 

Looking for the best template rule

For each node that is processed by xsl:apply-templates , the XSLT processor looks for the best template rule to apply to it.

If the instructions select attribute is defined, the processor will look for the most appropriate template rule for that node. But if select isnt defined, the template rule that contains xsl:apply-templates is chosen for the current node.

However, in both of these cases, dont forget about the children. The current nodes children are also processed, so the XSLT processing engine goes through the same process of looking for the most appropriate template rule for each child. If a template rule is found matching that node, it will then be processed. But if not, then a built-in template rule is processed instead.

Heres a summary of the behavior of xsl:apply-templates :

  • Looks for the most appropriate template rule to apply for each node in the node set. If no template rule has been defined, xsl:apply-templates will apply a built-in template rule.

  • With no select attribute, processes all children.

 Remember   In addition to elements, xsl:apply-templates also applies text nodes that are children of the current node.

Consider a few examples to get a better grasp of its intended actions. I use the following XML fragment in Listing 4-3 as the source document in each of these.

Listing 4-3: miniscore.xml
start example
 <!-- miniscore.xml --> <score id="1"> <film>A Little Princess</film> <composer>Patrick Doyle</composer> <year>1995</year> <grade>100</grade> </score> 
end example
 

Using xsl:apply-templates on the score element, the template rule is defined as:

 <xsl:template match="score"> <xsl:apply-templates/> </xsl:template> 

This template rule processes the score node and its children (using built-in templates, which I discuss later in the chapter) to send their content (in other words, text nodes) to the result tree. Because the score element has no text content, no text is added to the result tree. But, because the score element has four child elements that have text nodes, the child elements content is transferred to the result document:

 A Little Princess Patrick Doyle 1995 100 

Using xsl:apply-templates with a select attribute, the template rule supplied is defined as follows :

 <xsl:template match="score"> <xsl:apply-templates select="grade"/> is the critic's rating for the musical score of <xsl:apply- templates select="film"/> </xsl:template> 

In this template rule, I apply the template specifically on the grade and film elements to add their content to the result tree. In between these two, I add literal text to the output. The result is:

 100 is the critic's rating for the musical score of A Little Princess 

The other children of the score element ( composer and year ) were not added to the result tree, because the xsl:apply-templates s select attribute didnt match these elements.

If you use xsl:apply-templates on an element with no children, only that particular element is processed:

 <xsl:template match="film"> <movie><xsl:apply-templates/></movie> </xsl:template> 

The preceding template sends the following text to the result tree:

 <movie>A Little Princess</movie> 

xsl:copy

You can use the xsl:copy element to do just what youd expect with a name like thatthis element copies the current node. It has a basic syntax of:

 <xsl:copy></xsl:copy> 

However, keep in mind some specific behaviors to this xsl:copy instruction:

  • Preserves the current nodes start and end tags during processing.

  • Doesnt copy children.

  • Doesnt copy attributes.

  • Includes content text only if you put an xsl:apply-templates inside the xsl:copy element. An empty xsl:copy ( <xsl:copy/> ) doesnt copy content.

  • Has no select attribute, so it acts only on the result of the template rules match pattern.

To illustrate , I use the miniscore.xml file (refer to Listing 4-3) as my source document. Using an empty xsl:copy element when the composer element is the match pattern, the code is defined as:

 <xsl:template match="composer"> <xsl:copy/> </xsl:template> 

The literal result of this template is <composer></composer> , but the XSLT processor shortens the empty tag to:

 <composer/> 

As you can see, the primary purpose of xsl:copy is to carry over the element tags. However, if you combine it with xsl:apply-templates , you copy both the tags and its content:

 <xsl:template match="composer"> <xsl:copy> <xsl:apply-templates/> </xsl:copy> </xsl:template> 

This template outputs:

 <composer>Patrick Doyle</composer> 

When you use xsl:copy and xsl:apply-templates on a current node that has children, the template rule copies the current nodes tags and the content of the children. For example:

 <xsl:template match="score"> <xsl:copy> <xsl:apply-templates/> </xsl:copy> </xsl:template> 

Results in:

 <score> A Little Princess Patrick Doyle 1995 100 </score> 

xsl:copy-of

xsl:copy-of may be similar in name to xsl:copy , but its behavior is quite distinct. It has a basic syntax of:

 <xsl:copy-of select="expression"/> 

While xsl:copy provides a carbon copy of some parts of the returned node set, xsl:copy-of does moreit duplicates everything inside the current node. Specifically, xsl:copy-of :

  • Copies all the nodes returned from its required select attribute.

  • Preserves all element tags during processing.

  • Copies children, attributes, and content.

  • Keeps any comments or other processing instructions in the copy.

To copy the score element from the miniscore.xml (refer to Listing 4-3) to a new result document, I set up a new template rule. The template rule for copying the score element as is from the source tree to the result tree is defined as:

 <xsl:template match="score"> <xsl:copy-of select="."/> </xsl:template> 

The template rules match pattern returns a score element, and the . expression inside the select attribute of the xsl:copy-to returns the current node (and all its children), producing the following output:

 <score id="1"> <film>A Little Princess</film> <composer>Patrick Doyle</composer> <year>1995</year> <grade>100</grade> </score> 

The select attribute of the xsl:copy-of element determines what is copied to the result tree. Suppose you define a more limited template rule:

 <xsl:template match="score"> <xsl:copy-of select="year"/> </xsl:template> 

This template rule results in a literal copy of only the year element (both tags and content):

 <year>1995</year> 

xsl:value-of

The xsl:value-of instruction is used when you want to convert part of the XML source to a string (plain text). It has a basic syntax of:

 <xsl:value-of select="expression"/> 

This instruction wants nothing to do with producing XML tags, so you never get elements or attributes when you use it. Specifically, the xsl:value-of element has the following behavior:

  • Converts the result from its required select attribute to a string and adds it as a text node to the result tree. If the result is a single node, its contents are converted. If the result is a node set, the contents of the first node are used for processing.

  • Removes element tags during processing.

  • Doesnt convert attributes of the context node.

  • Is combined with other text nodes that surround it before being added to the result tree.

Using the miniscore.xml file in Listing 4-3 as the source, if I use xsl:value-of on a single element ( film ), the template rule looks like:

 <xsl:template match="score"> <xsl:value-of select="film"/> </xsl:template> 

The film element is converted to text:

 A Little Princess 

xsl:value-of can also be used to convert an attribute to a string. For example, if I use a special @ character in the select attribute to denote an attribute:

 <xsl:template match="score"> <xsl:value-of select="@id"/> </xsl:template> 

It returns the following output:

 1 

Table 4-2 summarizes the behavior of xsl:copy , xsl:copy-of , and xsl:value-of .

Table 4-2: Parts Included in a Result Tree for Each Element

Element

Children

Attributes

Start/End tags

Content

select attribute

xsl:copy

No

No

Yes

No (Yes, with xsl:apply-templates )

None

xsl:copy-of

Yes (all children)

Yes

Yes

Yes

Required

xsl:value-of

Yes

No

No

Yes

Required

 Remember   A common mistake many XSLT stylesheet authors make is using a match attribute in place of the select attribute in an xsl:copy-of , xsl: apply-templates , or xsl:value-of instruction. Youll get a processing error if this occurs in your stylesheet.

  
 
 
2000-2002    Feedback


XSLT For Dummies
XSLT for Dummies
ISBN: 0764536516
EAN: 2147483647
Year: 2002
Pages: 148

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