prickett

 

XSLT

Page history last edited by todd 2 yrs ago

XSLT

 


 

General Concepts

XSLT walks elements by matching templates. When an element is matched, XSLT will not walk any children of that element unless instructed to do so by an apply-template command. It will, however, walk any elements prior to the current element, using the default template if necessary, to process them.

 

Simple Transformation using Templates

 

XML to transform:

<?xml version="1.0"?>
<root>
<name order="1">
<first>tom</first>
<last>jones</last>
</name>
<name order="2">
<first>bill</first>
<last>crosby</last>
</name>
<name order="3">
<first>pink</first>
<last>floyd</last>
</name>
</root>

 

XSLT:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="first">
First Name: <xsl:value-of select="text()" />
</xsl:template>
<xsl:template match="last">
Last Name: <xsl:value-of select="text()" />
</xsl:template >
<xsl:template match="name">
Order: <xsl:value-of select="@order" />
<xsl:apply-templates />
</xsl:template >
</xsl:stylesheet>

 

Results:

Order: 1
First Name: tom
Last Name: jones
Order: 2
First Name: bill
Last Name: crosby
Order: 3
First Name: pink
Last Name: floyd

 

Default Templates

If an element is not explicitly handled, XSLT applies a default template which simply dumps the element's contents.

root
|
-------------------
name              name
|                 |
----------------  -----------------
first          last first          last

In the above, if you match="/", and have only a template defined matching first, the default template is applied to root, then name, uses the defined template for first, and finally reverts to the default template for last.

 

Using the above XML and XSLT, I'll comment out the template that handles last to demonstrate this.

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="first">
First Name: <xsl:value-of select="text()" />
</xsl:template>
<!-- xsl:template match="last">
Last Name: <xsl:value-of select="text()" />
</xsl:template -->
<xsl:template match="name">
Order: <xsl:value-of select="@order" />
<xsl:apply-templates />
</xsl:template >
</xsl:stylesheet>

 

The results show that last was still printed out, thanks to the default template (if root had any text nodes, they too would have printed using the default template).

 

Order: 1
First Name: tomjones
Order: 2
First Name: billcrosby
Order: 3
First Name: pinkfloyd

To avoid printing out last you could either change the apply-template in the template matching "name" to be:

<xsl:template match="name">
Order: <xsl:value-of select="@order" />
<xsl:apply-templates match="first" />
</xsl:template >

Or, eat the last element by giving it a blank template:

<xsl:template match="last" />

Or, be selective in the initial template

<xsl:template match="/">
<xsl:apply-templates match="root/name/first" />
</xsl:template>
<xsl:template match="first">
First Name: <xsl:value-of select="text()" />
</xsl:template> 

 

 

Using for-each loops rather than templates:

 

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="root">
<xsl:for-each select="name" >
Order: <xsl:value-of select="@order" />
First Name: <xsl:value-of select="first" />
Last Name: <xsl:value-of select="last" />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet> 

 

Results: (the same as the first example - using templates)

Order: 1
First Name: tom
Last Name: jones
Order: 2
First Name: bill
Last Name: crosby
Order: 3
First Name: pink
Last Name: floyd

 

Attributes

XSLT walks elements only, NOT nodes. That means you must first navigate to an attribute's owning element before you can match it in a template.

 

This won't work:

<xsl:template match="/">
<xsl:apply-templates select="@order"/>
</xsl:template>

 

This will:

<xsl:template match="/">
<xsl:apply-templates select="root/name"/>
</xsl:template>
<xsl:template match="name">
<xsl:value-of select="@order" />
</xsl:template>

 

 

server monitoring

Comments (0)

You don't have permission to comment on this page.