Advanced XSLT II. Iteration in XSLT we sometimes wish to apply the same transform to a set of nodes we iterate through a node set the node set is defined.
Post on 28-Mar-2015
229 Views
Preview:
Transcript
Advanced XSLT II
Iteration in XSLT
• we sometimes wish to apply the same transform to a set of nodes
• we iterate through a node set
• the node set is defined by an XPath expression
• we use a for-each element to control the iteration
<xsl:for-each>
• Applies processing to all nodes in a given node set
• select attribute contains XPath expression defining the node set
<xsl:for-each select=“???”>• the current node changes at each iteration of
for-each– changes the context for transforms of content
example
• we have XML data for a tutorial, divided into sections
• we wish to produce a numbered contents list in HTML
• we use for-each twice to create a numbered heading and a list of sections
• we use the position() function for the numbering
<tutorial> <section>
<title>XML Tutorial</title> <panel> <title>XML and DTDs</title> </panel> <panel> <title>XPath and XSLT</title> </panel>
</section> <section>
<title>XSLT Tutorial</title> <panel> <title>XML and XSLT</title> </panel>
</section><!-- more sections follow – not shown -->
</tutorial>
The Data
<h1>Section 1. XML Tutorial</h1>
<ul>
<li>1. XML and DTDs</li>
<li>2. XPath and XSLT</li>
</ul>
<h1>Section 2. XSLT Tutorial</h1><ul>
<li>1. title>XML and XSLT </li></ul>
… and so on for each section
The Desired Output
<xsl:template match = "tutorial"> <xsl:apply-templates select="section"/> </xsl:template>
<xsl:template match = "section"> <h1><xsl:text>Section </xsl:text> <xsl:value-of select = "position()" /> <xsl:text>. </xsl:text> <xsl:value-of select = "title" /></h1><ul> <xsl:apply-templates select="panel"/> </ul> </xsl:template>
<xsl:template match = "panel"> <li><xsl:value-of select = "position()" /> <xsl:text>. </xsl:text> <xsl:value-of select = "title" /></li> </xsl:template>
<xsl:template match = “tutorial”> <xsl:for-each select=“section”> <h1><xsl:text>Section </xsl:text> <xsl:value-of select = “position()” /> <xsl:text>. </xsl:text> <xsl:value-of select = “title” /></h1> <ul>
<xsl:for-each select = “panel”> <li><xsl:value-of select = “position()” /> <xsl:text>. </xsl:text> <xsl:value-of select = “title” /></li></xsl:for-each>
</ul> </xsl:for-each></xsl:template
example - notes
• for-each select=“section” selects all section nodes in the current tutorial– position() will number the sections in
document order
• for-each select=“panel” selects all panel nodes in the current section
• this is just a nested loop!
modes
• Sometimes you may wish to transform the same node in more than one way
• The transform for a node is defined in a template
• A mode attribute is available for template and apply-templates elements
• This allows more than one template to be defined for any node
example
• XML data for a “famous scientists” website
• The data contains a name element for each person featured on the site.
• We use mode to achieve two different presentations of name – table of contents– personal data entry
<?xml version = “1.0”?>
<people>
<person born=“1912” died=“1954”>
<name><first_name>Alan</first-name>
<last_name>Turing</last_name>
</name>
<profession>computer scientist</profession>
<profession>mathematician</profession>
<profession>cryptographer</profession>
</person>
<!-- continued on next page -->
The Data
<!-- continued from previous page -->
<person born=“1918” died=“1988”>
<name><first_name>Richard</first-name>
<middle_initial>P</middle_initial>
<last_name>Feynman</last_name>
</name>
<profession>physicist</profession>
<hobby>playing the bongoes</hobby>
</person>
</people>
The Data
The Desired Output
<ul>
<li>Turing, Alan</li>
<li>Feynman, Richard</li>
</ul>
Name: Alan Turing <br />
Born: 1912 <br />
Died: 1954 <br />
Professions: computer scientist, mathematician, cryptographer <br />
Hobbies: none known
<xsl:template match = "people"> <html><head> <title>Famous Scientists</title></head><body> <ul> <xsl:for-each select = "person"> <li><xsl:value-of select = "name/last_name" />, <xsl:value-of select = "name/first_name" /></li> </xsl:for-each> </ul> <xsl:for-each select = "person"> Name: <xsl:value-of select="name/first_name" />
<xsl:value-of select="name/last_name" /><br/> Born: <xsl:value-of select="@born" /> <br/> Died: <xsl:value-of select="@died" /> <br/> </xsl:for-each> </body></html></xsl:template>
<?xml version = “1.0”?><xsl:stylesheet version = “1.0” xmlns:xsl=“http://www.w3.org/1999/XSL/Transform”>
<xsl:template match = “people”>
<html><head>
<title>Famous Scientists</title></head><body>
<ul>
<xsl:apply-templates select = “person” mode = “toc” />
</ul>
<xsl:apply-templates select = “person” />
</body></html>
</xsl:template>
<!-- stylesheet continues on next page-->
<!-- specify the template mode for person -->
<xsl:template match = “person” mode = “toc”>
<xsl:apply-templates select=“name” mode=“toc”/>
</xsl:template>
<!--Table of Contents mode template for name-->
<xsl:template match = “name” mode = “toc”>
<li><xsl:value-of select = “last_name” />,
<xsl:value-of select = “first_name” /></li>
</xsl:template>
<!-- default mode template for person-->
<xsl:template match = “person”>
Name: <xsl:value-of select=“first-name” />
<xsl:value-of select=“last-name” /><br/>
Born: <xsl:value-of select=“@born” /> <br/>
Died: <xsl:value-of select=“@died” /> <br/>
<!-- complete the rest as an exercise -->
</xsl:template>
<!-- end of stylesheet -->
</xsl:stylesheet>
attribute value templates
• allows attribute values derived from the source to be set in the output
• example<xsl:template match = “name”><name first = “{first_name}”
initial = “{middle_initial}” last = “{last_name}” />
</xsl:template>
<xsl:call-template>
• specifies a particular template to be invoked
• perhaps not related directly to a node-set– e.g. to add boilerplate start_html markup
• template must have a name attribute
• <xsl:call-template> calls the template by name
<xsl:template name = “createMasthead”>
<!—Interesting stuff that generates the masthead
goes in here -->
</xsl:template>
…
<xsl:template match = “/”>
<html>
<head><title>some-title</title></head>
<body>
<xsl:call-template name = “createMasthead” />
<xsl:param>, <xsl:with-param>
• <xsl:param> defines parameters for templates• parameters can be passed to templates from either
call-template or apply-template elements containing <xsl:with-param> elements
• name attribute names the parameter• select attribute (or content) defines the value of the
parameter
<apply-templates><call-template><with-param>
<template><param>
XSLT
processing flow
reference to
template and parameter passed
return to XSLT processing flow
<xsl:template name = “addTableCell”>
<xsl:param name = “bgcolor” select = “’blue’” />
<xsl:param name = “width”>
<xsl:text>150</xsl:text>
</xsl:param>
<td width = “$width” bgcolor = “$bgcolor”>
<!-- cell content goes here -->
</td>
</xsl:template>
…
<xsl:call-template name = “addTableCell”>
<xsl:with-param name = “width” select = “./@width” />
</xsl:call-template>
<xsl:variable>
• allows values to be stored to assist with processing flow logic
• name attribute names the variable
• select attribute (or content) defines the value of the variable
• value can also be defined from element content
<xsl:variable name = “x” />
<!– variable $x defined, value is the empty string -->
<xsl:variable name = “color” value = “’blue’” />
<!-- variable $color has as value the string “blue” -->
<xsl:variable name = “y”>
<xsl:choose>
<xsl:when test = “$x > 7”>
<xsl:text>13</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>15</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!-- essentially, if $x > 7, $y = 13 else $y = 15 -->
<xsl:sort>
• appears inside <xsl:apply-templates> or inside <xsl:for-each>
• sorts a node-set according to some criterion
• successive sort elements impose sub-orders
• select attribute defines the sorting criterion
• data-type defines the type of sort– text (the default)– number
<xsl:for-each select = “addressbook/address”>
<xsl:sort select = “name/last-name” />
<xsl:sort select = “name/first-name” />
<xsl:apply-templates select = “.” />
</xsl:for-each>
<!-- sorts addresses by last then first name -->
<xsl:for-each select = “number-list/number”>
<xsl:sort select = “.” data-type = “number” />
<xsl:value-of select = “.” />
</xsl:for-each>
<!-- sorts numbers in numerical order -->
<xsl:sort>
more sort attributes
• order– ascending (default)– descending
• case-order– upper-first– lower-first
document ( )
• converts a parameter into a URI– relative to current document– second parameter gives an alternative base URI
• returns a node-set associated with the URI
• allows content to be extracted from multiple XML documents
• without parameter defaults to current document
multiple XML files
XSLTdocument
XSLTprocessor
outputdocument
set oftemplate rules
match elements and replace using template rules
XMLsource
XMLsource
XMLsource
XMLsource
XMLsource
XMLsource
masterdocument
document()
<report>
<title>Fridge Contents</title>
<fml file = “fridge1.xml” />
<fml file = “fridge2.xml” />
<fml file = “fridge3.xml” />
</report>
<xsl:template match = “/”>
<xsl:for-each select = “/report/fml”>
<xsl:apply-templates select=“document(@file)”/>
</xsl:for-each>
</xsl:template>
<!--followed by templates for fridge elements-->
XML
XSLT
XSLT extensions• extension elements are passed to external
code (extension functions) for processing– Java, Perl, C# etc.
• extends power of XSLT to arbitrary transformations
• implementation varies between XSLT processors– Xalan, Saxon, XT all allow extensions, but in
different ways
Useful websites• Standards:
– www.w3.org/Style/XSL/- administrates xsl std• www.w3.org/TR/xslt
• Tutorials/Forums– www.w3schools.com/xsl– www.learn-xslt-tutorial.com/– www.xml.com– www.tizag.com/xmlTutorial/xslttutorial.php
top related