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

Category:

Documents

0 Downloads

Preview:

Click to see full reader

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)&gt;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)&gt;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” />&nbsp;

<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 &gt; 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