Advanced XSLT. Branching in XSLT XSLT is functional programming –The program evaluates a function –The function transforms one structure into another.
Post on 28-Mar-2015
223 Views
Preview:
Transcript
Advanced XSLT
Branching in XSLT
• XSLT is functional programming– The program evaluates a function– The function transforms one structure into
another– The function is written in XML
• The transform flow can branch depending on the content
• Similar idea to an if statement in OOP
<xsl:if>
• The if element allows the transform to branch
• It contains further processing instructions
• Branching is controlled by a Boolean attribute called test
• if test has value true, the transform branches through the content of if
Boolean Values
• test is an XML attribute of if– its value is an XPath expression– this will be interpreted as a Boolean
• standard rules apply to translate the results of XPath expressions to Booleans
• XPath typically evaluates to the following types:– number, node set, string
translation to Boolean values
• Number+0 or -0 or NaN false, all other numbers true
• node-set– empty node-set false, non-empty node-set true
• String– empty string false, all other strings true
• true() and false() functions
True or false?
<xsl:if test = “true()”>
- always true
<xsl:if test = “-0”>
- returns false
<xsl:if test = “false”>
- true if and only if non-empty node-set
<xsl:if test = “count(zone)>2”>
- depends on number of zones
examples
example
• Some XML data contains zone elements
• If the number of zone elements is greater than 2, we wish to produce some HTML
• A template for zone has been predefined
• We will use if to decide whether to transform the zone elements into HTML
<xsl:if test = “count(zone)>2”>
<!the following instructions are processed if
and only if the number of zone elements in the
current context is greater than 2 -->
<h1>Applicable Zones</h1>
<xsl:apply-templates select = “zone” />
</xsl:if>
example
Example - notes
• We have a separate template for zone
• This can be developed separately from the if transform
• An XSLT can be built up from different parts
• Use templates to divide your transform into easy-to-program steps
Branching in XSLT
• Several nested if elements become difficult to program
• The choose element plays the role of a case statement in XSLT
• The transform will branch into one of a choice of transforms depending on the value of an XPath expression
<xsl:choose>
• contains one or more <xsl:when> elements– when operates exactly like if– test attribute with Boolean XPath value– content is further transform instructions
• choose may contain one optional otherwise element– represents the default case– content is further transform instructions
example
• we will define an attribute value using choose
• the attribute will be a bgcolor for table rows
• we want the rows to alternate between orange and green
• we use the position() function in an XPath expression for our test
<xsl:template match = “zone”><tr>
<xsl:attribute name = “bgcolor”>
<xsl:choose>
<xsl:when test = “position()mod2=0”>
<xsl:text>orange</xsl:text>
</xsl:when><xsl:otherwise>
<xsl:text>green</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:apply-templates select=“*”/>
</tr></xsl:template>
example - notes
• the attribute element can be used to define an attribute during the transform– can be inserted in output – see later
• the text element is used to precisely define literal text content
• the example again relies on pre-defined templates for other elements (the content of zone)
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
• 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>
<!-- 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>
… and so on for each section
The Desired Output
<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
<?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” select = “’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
top related