©csw group ltd 2005 intermediate xslt bob ducharme bob@snee.com these slides: 1.0
Post on 14-Dec-2015
212 Views
Preview:
TRANSCRIPT
©CSW Group Ltd 2005
Intermediate XSLTBob DuCharme
www.snee.com/bobbob@snee.com
these slides: www.snee.com/xml
1.0
Outline
• Variables and parameters
• Named templates and parameters
• xsl:for-each and “looping”
• XSLT extensions and EXSLT
• Using keys for faster lookups
• XSLT and browsers
Variables
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes"/>
<xsl:variable name="winnerName">John</xsl:variable>
<xsl:template match="test"> <xsl:text>Congratulations, </xsl:text> <xsl:value-of select="$winnerName"/> <xsl:text>, you are a winner!</xsl:text> <xsl:apply-templates/></xsl:template>
</xsl:stylesheet>
Input document:
<test/> Output:
Congratulations, John, you are a winner!
Passing Parameters to Stylesheets
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes"/>
<xsl:param name="winnerName">John</xsl:param>
<xsl:template match="test"> <xsl:text>Congratulations, </xsl:text> <xsl:value-of select="$winnerName"/> <xsl:text>, you are a winner!</xsl:text> <xsl:apply-templates/></xsl:template>
</xsl:stylesheet>
Same input document, same result, but when we override the default parameter value:
C:\>saxon temp.xml test.xsl winnerName=JaneCongratulations, Jane, you are a winner!
Named Templates
<xsl:template name="boldIt"> <b><xsl:apply-templates/></b></xsl:template>
<xsl:template match="winery"> <p><xsl:call-template name="boldIt"/></p></xsl:template>
<xsl:template match="product"> <p><xsl:call-template name="boldIt"/></p></xsl:template>
<xsl:template match="year | price"> <p><xsl:apply-templates/></p></xsl:template>
Passing Parameters to Named Templates
<xsl:template name="titles"> <xsl:param name="headerElement">h4</xsl:param> <xsl:element name="{$headerElement}"> <xsl:apply-templates/> </xsl:element> </xsl:template>
<xsl:template match="chapter/title"> <xsl:call-template name="titles"> <xsl:with-param name="headerElement">h1</xsl:with-param> </xsl:call-template> </xsl:template>
<xsl:template match="section/title"> <xsl:call-template name="titles"> <xsl:with-param name="headerElement" select="'h2'"/> </xsl:call-template> </xsl:template>
Iterating across a set of nodes<a> <b>3</b> <c>10</c> <b>4</b> <c>20</c> <b>5</b></a>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="a"> <xsl:for-each select="b"> <xsl:value-of select=". + 5"/> <xsl:text> </xsl:text> </xsl:for-each> </xsl:template></xsl:stylesheet>
output:
<?xml version="1.0" encoding="UTF-8"?>8 9 10
Repetition
<xsl:template name="hyphens"> <xsl:param name="howMany">1</xsl:param> <xsl:if test="$howMany > 0">
<!-- Add 1 hyphen to result tree. --> <xsl:text>-</xsl:text>
<!-- Print remaining ($howMany - 1) hyphens. --> <xsl:call-template name="hyphens"> <xsl:with-param name="howMany" select="$howMany - 1"/> </xsl:call-template> </xsl:if></xsl:template>
Testing the recursive template rule
<xsl:template match="sample">
Print 1 hyphen: <xsl:call-template name="hyphens"/>
Print 20 hyphens: <xsl:call-template name="hyphens"> <xsl:with-param name="howMany" select="20"/> </xsl:call-template>
Print 0 hyphens: <xsl:call-template name="hyphens"> <xsl:with-param name="howMany" select="0"/> </xsl:call-template>
</xsl:template>
Recursive template rule: result
Print 1 hyphen:
-
Print 20 hyphens:
--------------------
Print 0 hyphens:
XSLT Extension functions
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:saxon="http://saxon.sf.net/">
<xsl:template match="*">
<xsl:value-of select="saxon:path()"/>
<xsl:text>
</xsl:text>
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
Testing the extension function
• Source document:<a>
<b/>
<b><c color="red">test</c></b>
<b/>
</a>
• Result:
/a /a/b[1] /a/b[2]/a/b[2]/c[1]test /a/b[3]
Extension elements (and attributes)
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:saxon="http://saxon.sf.net/" extension-element-prefixes="saxon">
<xsl:variable name="i" select="0" saxon:assignable="yes"/>
<xsl:template match="/">
<saxon:while test="$i < 10"> The value of i is <xsl:value-of select="$i"/> <saxon:assign name="i" select="$i+1"/> </saxon:while>
</xsl:template>
</xsl:stylesheet>
Extension element test output
The value of i is 0
The value of i is 1
The value of i is 2
The value of i is 3
The value of i is 4
The value of i is 5
The value of i is 6
The value of i is 7
The value of i is 8
The value of i is 9
Checking for extension support (option 1)
<saxon:while test="$i < 10">
The value of i is <xsl:value-of select="$i"/>
<xsl:fallback>
<xsl:message>Your XSLT processor doesn't
support saxon:while.</xsl:message>
</xsl:fallback>
<saxon:assign name="i" select="$i+1"/>
</saxon:while>
Checking for extension support (option 2)<xsl:choose>
<xsl:when test="element-available('saxon:while')">
<saxon:while test="$i < 10">
The value of i is <xsl:value-of select="$i"/>
<saxon:assign name="i" select="$i+1"/>
</saxon:while>
</xsl:when>
<xsl:otherwise>
<xsl:message>Your XSLT processor doesn't support
saxon:while.</xsl:message>
</xsl:otherwise>
</xsl:choose>
checking for extension function support: function-available()
EXSLT
• Saxon documentation on its extensions:
“ Before using a Saxon extension, check whether there is an equivalent EXSLT extension available. EXSLT extensions are more likely to be portable across XSLT processors.”
• http://www.exslt.org
Some EXSLT extensions (pt 1)
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common" xmlns:math="http://exslt.org/math" xmlns:date="http://exslt.org/dates-and-times">
<xsl:template match="/">
exsl:object-type(3): <xsl:value-of select="exsl:object-type(3)"/> exsl:object-type('potrzebie'): <xsl:value-of select="exsl:object-type('potrzebie')"/> exsl:object-type(2 > 1): <xsl:value-of select="exsl:object-type(2 > 1)"/>
Some EXSLT extensions (pt 2)
math:constant('PI',4): <xsl:value-of select="math:constant('PI',4)"/> math:constant('PI',12): <xsl:value-of select="math:constant('PI',12)"/> math:sqrt(256): <xsl:value-of select="math:sqrt(256)"/>
date:date-time: <xsl:value-of select="date:date-time()"/> date:day-name: <xsl:value-of select="date:day-name()"/>
</xsl:template>
</xsl:stylesheet>
EXSLT demo result exsl:object-type(3): number exsl:object-type('potrzebie'): string exsl:object-type(2 > 1): boolean math:constant('PI',4): 3.1415 math:constant('PI',12): 3.141592653589 math:sqrt(256): 16 date:date-time: 2005-06-25T11:24:12-04:00 date:day-name:
Saturday
• same result with Saxon and Xalan Java!
Declaring and using lookup keys
• we have: <shirts>
<colors> <color cid="c1">yellow</color>
<color cid="c4">blue</color>
<!-- similar color elements --> <color cid="c7">orange</color> <color cid="c7">green</color> </colors>
<shirt colorCode="c4">oxford button-down</shirt> <shirt colorCode="c1">poly blend, straight collar</shirt> <shirt colorCode="c6">monogrammed, tab collar</shirt>
</shirts>
• we want: blue oxford button-down
yellow poly blend, straight collar
white monogrammed, tab collar
Without keys<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="shirt">
<xsl:variable name="shirtColorCode"
select="@colorCode"/>
<xsl:value-of
select="/shirts/colors/color[@cid = $shirtColorCode]"/>
<xsl:text> </xsl:text><xsl:apply-templates/><xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="color"/>
</xsl:stylesheet>
With keys
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:key name="colorNumKey" match="color" use="@cid"/>
<xsl:template match="colors"/>
<xsl:template match="shirt"> <xsl:value-of select="key('colorNumKey',@colorCode)"/> <xsl:text> </xsl:text><xsl:apply-templates/> </xsl:template>
</xsl:stylesheet>
How key lookup works
More lookups (part 1)<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:key name="colorNumKey" match="color" use="@cid"/> <xsl:key name="colorKey" match="color" use="."/>
<xsl:variable name="testVar">c4</xsl:variable> <xsl:variable name="keyName">colorKey</xsl:variable>
<xsl:template match="colors">
Looking up the color name with the color ID: c3's color: <xsl:value-of select="key('colorNumKey','c3')"/> c4's color: <xsl:value-of select="key('colorNumKey',$testVar)"/> c8's color: <xsl:value-of select="key('colorNumKey','c8')"/> c7's colors: <xsl:for-each select="key('colorNumKey','c7')"><xsl:value-of select="."/><xsl:text> </xsl:text> </xsl:for-each>
More lookups (part 2)
Looking up the color ID with the color name: blue's cid: <xsl:value-of select="key('colorKey','blue')/@cid"/> black's cid: <xsl:value-of select="key($keyName,'black')/@cid"/> gray's cid: <xsl:value-of select="key('colorKey','gray')/@cid"/>
</xsl:template>
<!-- Don't bother outputting shirt contents for this example. -->
<xsl:template match="shirt"/>
</xsl:stylesheet>
More lookups: result
Looking up the color name with the color ID:c3's color: redc4's color: bluec8's color:c7's colors:orange green Looking up the color ID with the color name:blue's cid: c4black's cid: c2gray's cid:
Muenchian Grouping<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="files-by-project" match="file" use="@project"/>
<xsl:template match="files"> <html><body> <xsl:for-each select= "file[count(. | key('files-by-project', @project)[1]) = 1]"> <xsl:sort select="@project"/> <h1><xsl:value-of select="@project" /></h1> <xsl:for-each select="key('files-by-project', @project)"> <xsl:sort select="@name"/> <p><xsl:value-of select="@name"/> <xsl:text>,</xsl:text> <xsl:value-of select="@size"/> bytes</p> </xsl:for-each> </xsl:for-each> </body></html> </xsl:template>
</xsl:stylesheet>
Muenchian Grouping: result
<html> <body> <h1>jupiter</h1> <p>gadabout.pas,685 bytes</p> <p>kwatz.xom,43 bytes</p> <p>potrzebie.dbf,1102 bytes</p> <h1>mars</h1> <p>schtroumpf.txt,389 bytes</p> <p>swablr.eps,4313 bytes</p> <p>ummagumma.zip,2441 bytes</p> <h1>neptune</h1> <p>batboy.wks,424 bytes</p> <p>mondegreen.doc,1993 bytes</p> <p>paisley.doc,988 bytes</p> </body></html>
Web Browsers and XSLT
W3C Recommendation "Associating Style Sheets
with XML documents"
(http://www.w3.org/TR/xml-stylesheet) shows how:
<?xml-stylesheet href="squareAsHTML.xsl" type="text/xsl" ?><numbers> <number>2</number> <number>11</number> <number>100</number> <number>-5</number></numbers>
Web Browsers and XSLT (part 1)<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><!-- squareAsHTML.xsl: create an HTML document with a statement about the square of each "number" element read from the source tree. -->
<xsl:template match="/"> <!-- Set up web page --> <html> <head> <title>Squares</title> <style> <!-- Put a little CSS in --> body { font-family: arial,helvetica; } h1 { font-size: 14pt } p { font-size: 10pt} </style> </head> <body> <h1>Squares</h1> <xsl:apply-templates/> </body> </html> </xsl:template>
Web Browsers and XSLT (part 2)
<xsl:template match="number"> <xsl:variable name="value" select="."/> <p> <xsl:text>The square of </xsl:text> <xsl:value-of select="$value"/> <xsl:text> is </xsl:text> <xsl:value-of select="$value * $value"/>.</p> </xsl:template>
</xsl:stylesheet>
You could create your HTML like this:
saxon -o numbers.html numbers.xml squareAsHTML.xsl
XSLT 2.0
• Lots more built-in functions
• Writing your own functions
• Regular expressions
• Grouping output by values
• Tokenizing strings
• Typing awareness
top related