XML Tutorial/XSLT stylesheet/template
Содержание
- 1 A template can match from a selection of location paths, individual paths being separated with "|".
- 2 Call template based function recursively
- 3 If you want to include descendants of the node, you have to explicitly request their templates.
- 4 Mark a parameter as requred
- 5 match=county[starts-with(.,K)]
- 6 Parts of XML document to which template should be applied are determined by location paths
- 7 Processing always starts with the template match="/"
- 8 template match=state priority=2
- 9 Template with parameters
- 10 the default action in the absence of priority attributes.
- 11 This priority order can be specified with the priority attributte.
- 12 When a template for the node exists, there is no default processing invoked
- 13 While XSLT does not define while and for loops, their behavior can be simulated.
- 14 With modes an element can be processed multiple times, each time producing a different result.
- 15 without if
- 16 xsl:template match="/"
A template can match from a selection of location paths, individual paths being separated with "|".
File: Data.xml
<?xml version="1.0" encoding="utf-8"?>
<employee>
<firstName>Joe</firstName>
<surname>Smith</surname>
</employee>
File: Transform.xslt
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="firstName|surname">
<div>
<xsl:text>[template: </xsl:text>
<xsl:value-of select="name()" />
<xsl:text> outputs </xsl:text>
<xsl:apply-templates />
<xsl:text> ]</xsl:text>
</div>
</xsl:template>
</xsl:stylesheet>
Output:
<?xml version="1.0" encoding="UTF-8"?>
<div>[template: firstName outputs Joe ]</div>
<div>[template: surname outputs Smith ]</div>
Call template based function recursively
File: Data.xml
<?xml version="1.0"?>
<numbers>
<x>4</x>
<y>3.2</y>
<z>11</z>
</numbers>
File: Transform.xslt
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="text" />
<xsl:variable name="iterations" select="8" />
<xsl:template name="myFunction">
<xsl:param name="i">1</xsl:param>
<xsl:param name="myValue">0</xsl:param>
<xsl:choose>
<xsl:when test="$i <= $iterations">
<xsl:call-template name="myFunction">
<xsl:with-param name="i" select="$i + 4" />
<xsl:with-param name="myValue"
select="$myValue + (4 div $i)" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$myValue" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="/">
<xsl:call-template name="myFunction" />
</xsl:template>
</xsl:stylesheet>
Output:
4.8
If you want to include descendants of the node, you have to explicitly request their templates.
File: Data.xml
<?xml version="1.0" encoding="utf-8"?>
<data>
<AAA id="a1" pos="start">
<BBB id="b1"/>
<BBB id="b2"/>
</AAA>
<AAA id="a2">
<BBB id="b3"/>
<BBB id="b4"/>
<CCC id="c1">
<DDD id="d1"/>
</CCC>
<BBB id="b5">
<CCC id="c2"/>
</BBB>
</AAA>
</data>
File: Transform.xslt
<?xml version="1.0" encoding="utf-8"?>
<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="/data">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="AAA">
<div style="color:purple">
<xsl:value-of select="name()"/>
<xsl:text> id=</xsl:text>
<xsl:value-of select="@id"/>
</div>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="BBB">
<div style="color:blue">
<xsl:value-of select="name()"/>
<xsl:text> id=</xsl:text>
<xsl:value-of select="@id"/>
</div>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="CCC">
<div style="color:maroon">
<xsl:value-of select="name()"/>
<xsl:text> id=</xsl:text>
<xsl:value-of select="@id"/>
</div>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="DDD">
<div style="color:green">
<xsl:value-of select="name()"/>
<xsl:text> id=</xsl:text>
<xsl:value-of select="@id"/>
</div>
</xsl:template>
</xsl:stylesheet>
Output:
<?xml version="1.0" encoding="UTF-8"?>
<div style="color:purple">AAA id=a1</div>
<div style="color:blue">BBB id=b1</div>
<div style="color:blue">BBB id=b2</div>
<div style="color:purple">AAA id=a2</div>
<div style="color:blue">BBB id=b3</div>
<div style="color:blue">BBB id=b4</div>
<div style="color:maroon">CCC id=c1</div>
<div style="color:green">DDD id=d1</div>
<div style="color:blue">BBB id=b5</div>
<div style="color:maroon">CCC id=c2</div>
Mark a parameter as requred
File: Transform.xslt
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:call-template name="date-formatter">
<xsl:with-param name="date" select="current-date()"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="date-formatter">
<xsl:param name="date" required="yes"/>
<xsl:value-of select="format-date($date, "[M01]/[D01]/[Y0001]")"/>
</xsl:template>
</xsl:stylesheet>
Output:
12/11/2008
match=county[starts-with(.,K)]
File: Data.xml
<?xml version="1.0" encoding="US-ASCII"?>
<state name="New York">
<county>Bristol</county>
<county>Kent</county>
<county>Newport</county>
<county>Providence</county>
<county>Washington</county>
</state>
File: Transform.xslt
<?xml version="1.0" encoding="US-ASCII"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/">
<county state="{state/@name}">
<xsl:apply-templates select="state" />
</county>
</xsl:template>
<xsl:template match="state">
<xsl:apply-templates select="county" />
</xsl:template>
<xsl:template match="county[starts-with(.,"K")]">
<first-match>
<xsl:apply-templates />
</first-match>
</xsl:template>
<xsl:template match="county[2]">
<last-match>
<xsl:apply-templates />
</last-match>
</xsl:template>
<xsl:template match="county">
<name>
<xsl:apply-templates />
</name>
</xsl:template>
</xsl:stylesheet>
Output:
<?xml version="1.0" encoding="UTF-8"?>
<county state="New York">
<name>Bristol</name>
<last-match>Kent</last-match>
<name>Newport</name>
<name>Providence</name>
<name>Washington</name>
</county>
Parts of XML document to which template should be applied are determined by location paths
File: Data.xml
<?xml version="1.0" encoding="utf-8"?>
<data>
<AAA id="a1" pos="start">
<BBB id="b1"/>
<BBB id="b2"/>
</AAA>
<AAA id="a2">
<BBB id="b3"/>
<BBB id="b4"/>
<CCC id="c1">
<DDD id="d1"/>
</CCC>
<BBB id="b5">
<CCC id="c2"/>
</BBB>
</AAA>
</data>
File: Transform.xslt
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="BBB">
<div style="color:purple">
<xsl:value-of select="name()"/>
<xsl:text> id=</xsl:text>
<xsl:value-of select="@id"/>
</div>
</xsl:template>
<xsl:template match="/source/AAA/CCC/DDD">
<p style="color:red">
<xsl:value-of select="name()"/>
<xsl:text> id=</xsl:text>
<xsl:value-of select="@id"/>
</p>
</xsl:template>
</xsl:stylesheet>
Output:
<?xml version="1.0" encoding="UTF-8"?>
<div style="color:purple">BBB id=b1</div>
<div style="color:purple">BBB id=b2</div>
<div style="color:purple">BBB id=b3</div>
<div style="color:purple">BBB id=b4</div>
<div style="color:purple">BBB id=b5</div>
Processing always starts with the template match="/"
File: Data.xml
<?xml version="1.0" encoding="utf-8"?>
<data>
<AAA id="a1" pos="start">
<BBB id="b1"/>
<BBB id="b2"/>
</AAA>
<AAA id="a2">
<BBB id="b3"/>
<BBB id="b4"/>
<CCC id="c1">
<DDD id="d1"/>
</CCC>
<BBB id="b5">
<CCC id="c2"/>
</BBB>
</AAA>
</data>
File: Transform.xslt
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="AAA">
<div style="color:purple">
<xsl:value-of select="name()"/>
<xsl:text> id=</xsl:text>
<xsl:value-of select="@id"/>
</div>
</xsl:template>
</xsl:stylesheet>
Output:
<?xml version="1.0" encoding="UTF-8"?>
<div style="color:purple">AAA id=a1</div>
<div style="color:purple">AAA id=a2</div>
template match=state priority=2
File: Data.xml
<?xml version="1.0" encoding="US-ASCII"?>
<state name="New York">
<county>Bristol</county>
<county>Kent</county>
<county>Newport</county>
<county>Providence</county>
<county>Washington</county>
</state>
File: Transform.xslt
<?xml version="1.0" encoding="US-ASCII"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/">
<county state="{state/@name}">
<xsl:apply-templates select="state" />
</county>
</xsl:template>
<xsl:template match="state" priority="2">
<xsl:apply-templates select="county" />
</xsl:template>
<xsl:template match="state" priority="1">
<xsl:apply-templates select="county[starts-with(.,"K")]" />
</xsl:template>
<xsl:template match="county">
<name>
<xsl:apply-templates />
</name>
</xsl:template>
</xsl:stylesheet>
Output:
<?xml version="1.0" encoding="UTF-8"?>
<county state="New York">
<name>Bristol</name>
<name>Kent</name>
<name>Newport</name>
<name>Providence</name>
<name>Washington</name>
</county>
Template with parameters
File: Transform.xslt
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:call-template name="test">
<xsl:with-param name="param1" select=""57""/>
<xsl:with-param name="param2" select=""93""/>
</xsl:call-template>
</xsl:template>
<xsl:template name="test">
<xsl:param name="param1"/>
<xsl:text>Value of $param1: </xsl:text>
<xsl:value-of select="$param1"/>
</xsl:template>
</xsl:stylesheet>
Output:
Value of $param1: 57
the default action in the absence of priority attributes.
File: Data.xml
<?xml version="1.0" encoding="utf-8"?>
<data>
<AAA id="a1" pos="start">
<BBB id="b1"/>
<BBB id="b2"/>
</AAA>
<AAA id="a2">
<BBB id="b3"/>
<BBB id="b4"/>
<CCC id="c1">
<CCC id="c2"/>
</CCC>
<BBB id="b5">
<CCC id="c3"/>
</BBB>
</AAA>
</data>
File: Transform.xslt
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:apply-templates select="//CCC"/>
</xsl:template>
<xsl:template match="CCC">
<h3 style="color:blue">
<xsl:value-of select="name()"/>
<xsl:text> (id=</xsl:text>
<xsl:value-of select="@id"/>
<xsl:text>)</xsl:text>
</h3>
</xsl:template>
<xsl:template match="CCC/CCC">
<h2 style="color:red">
<xsl:value-of select="name()"/>
<xsl:text> (id=</xsl:text>
<xsl:value-of select="@id"/>
<xsl:text>)</xsl:text>
</h2>
</xsl:template>
</xsl:stylesheet>
Output:
<?xml version="1.0" encoding="UTF-8"?><h3 style="color:blue">CCC (id=c1)</h3><h2 style="color:red">CCC (id=c2)</h2><h3 style="color:blue">CCC (id=c3)</h3>
This priority order can be specified with the priority attributte.
File: Data.xml
<?xml version="1.0" encoding="utf-8"?>
<data>
<AAA id="a1" pos="start">
<BBB id="b1"/>
<BBB id="b2"/>
</AAA>
<AAA id="a2">
<BBB id="b3"/>
<BBB id="b4"/>
<CCC id="c1">
<CCC id="c2"/>
</CCC>
<BBB id="b5">
<CCC id="c3"/>
</BBB>
</AAA>
</data>
File: Transform.xslt
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:apply-templates select="//CCC"/>
</xsl:template>
<xsl:template match="CCC" priority="3">
<h3 style="color:blue">
<xsl:value-of select="name()"/>
<xsl:text> (id=</xsl:text>
<xsl:value-of select="@id"/>
<xsl:text>)</xsl:text>
</h3>
</xsl:template>
<xsl:template match="CCC/CCC" priority="4">
<h2 style="color:red">
<xsl:value-of select="name()"/>
<xsl:text> (id=</xsl:text>
<xsl:value-of select="@id"/>
<xsl:text>)</xsl:text>
</h2>
</xsl:template>
</xsl:stylesheet>
Output:
<?xml version="1.0" encoding="UTF-8"?><h3 style="color:blue">CCC (id=c1)</h3><h2 style="color:red">CCC (id=c2)</h2><h3 style="color:blue">CCC (id=c3)</h3>
When a template for the node exists, there is no default processing invoked
File: Data.xml
<?xml version="1.0" encoding="utf-8"?>
<data> <AAA id="a1" pos="start">
<BBB id="b1"/>
<BBB id="b2"/>
</AAA>
<AAA id="a2">
<BBB id="b3"/>
<BBB id="b4"/>
<CCC id="c1">
<DDD id="d1"/>
</CCC>
<BBB id="b5">
<CCC id="c2"/>
</BBB>
</AAA>
</data>
File: Transform.xslt
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="AAA">
<div style="color:purple">
<xsl:value-of select="name()"/>
<xsl:text> id=</xsl:text>
<xsl:value-of select="@id"/>
</div>
</xsl:template>
<xsl:template match="BBB">
<div style="color:blue">
<xsl:value-of select="name()"/>
<xsl:text> id=</xsl:text>
<xsl:value-of select="@id"/>
</div>
</xsl:template>
<xsl:template match="CCC">
<div style="color:maroon">
<xsl:value-of select="name()"/>
<xsl:text> id=</xsl:text>
<xsl:value-of select="@id"/>
</div>
</xsl:template>
<xsl:template match="DDD">
<div style="color:green">
<xsl:value-of select="name()"/>
<xsl:text> id=</xsl:text>
<xsl:value-of select="@id"/>
</div>
</xsl:template>
</xsl:stylesheet>
Output:
<?xml version="1.0" encoding="UTF-8"?> <div style="color:purple">AAA id=a1</div>
<div style="color:purple">AAA id=a2</div>
While XSLT does not define while and for loops, their behavior can be simulated.
File: Data.xml
<?xml version="1.0" encoding="utf-8"?>
<data>
<AAA repeat="3"/>
<BBB repeat="2"/>
<CCC repeat="5"/>
</data>
File: Transform.xslt
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/data/*">
<paragraph>
<xsl:call-template name="for">
<xsl:with-param name="stop">
<xsl:value-of select="@repeat"/>
</xsl:with-param>
</xsl:call-template>
</p>
</xsl:template>
<xsl:template name="for">
<xsl:param name="start">1</xsl:param>
<xsl:param name="stop">1</xsl:param>
<xsl:param name="step">1</xsl:param>
<xsl:value-of select="name()"/>
<xsl:text/>
<xsl:if test="$start < $stop">
<xsl:call-template name="for">
<xsl:with-param name="stop">
<xsl:value-of select="$stop"/>
</xsl:with-param>
<xsl:with-param name="start">
<xsl:value-of select="$start + $step"/>
</xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Output:
<?xml version="1.0" encoding="UTF-8"?>
<paragraph>AAAAAAAAA</p>
<paragraph>BBBBBB</p>
<paragraph>CCCCCCCCCCCCCCC</p>
With modes an element can be processed multiple times, each time producing a different result.
In <stylesheet id="id3"/> one of the modes does not exist.
File: Data.xml
<?xml version="1.0" encoding="utf-8"?>
<data>
<AAA id="a1" pos="start">
<BBB id="b1"/>
<BBB id="b2"/>
</AAA>
<AAA id="a2">
<BBB id="b3"/>
<BBB id="b4"/>
<CCC id="c1">
<CCC id="c2"/>
</CCC>
<BBB id="b5">
<CCC id="c3"/>
</BBB>
</AAA>
</data>
File: Transform.xslt
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:apply-templates select="//CCC" mode="red"/>
<xsl:apply-templates select="//CCC" mode="blue"/>
<xsl:apply-templates select="//CCC"/>
</xsl:template>
<xsl:template match="CCC" mode="red">
<div style="color:red">
<xsl:value-of select="name()"/>
<xsl:text> id=</xsl:text>
<xsl:value-of select="@id"/>
</div>
</xsl:template>
<xsl:template match="CCC" mode="blue">
<div style="color:blue">
<xsl:value-of select="name()"/>
<xsl:text> id=</xsl:text>
<xsl:value-of select="@id"/>
</div>
</xsl:template>
<xsl:template match="CCC">
<div style="color:purple">
<xsl:value-of select="name()"/>
<xsl:text> id=</xsl:text>
<xsl:value-of select="@id"/>
</div>
</xsl:template>
</xsl:stylesheet>
Output:
<?xml version="1.0" encoding="UTF-8"?><div style="color:red">CCC id=c1</div><div style="color:red">CCC id=c2</div><div style="color:red">CCC id=c3</div><div style="color:blue">CCC id=c1</div><div style="color:blue">CCC id=c2</div><div style="color:blue">CCC id=c3</div><div style="color:purple">CCC id=c1</div><div style="color:purple">CCC id=c2</div><div style="color:purple">CCC id=c3</div>
without if
File: Data.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<africa>
<nation>
<name>Algeria</name>
<capital>Algiers</capital>
<population>32277942</population>
<cc>dz</cc>
</nation>
</africa>
File: Transform.xslt
<?xml version="1.0" encoding="US-ASCII"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:template match="africa">
<xsl:apply-templates select="nation" />
</xsl:template>
<xsl:template match="nation[population <= 10000000]">
<xsl:text> * </xsl:text>
<xsl:value-of select="name" />
<xsl:text> (<= 10M)</xsl:text>
<xsl:text> </xsl:text>
</xsl:template>
<xsl:template match="nation[population > 10000000]">
<xsl:text> * </xsl:text>
<xsl:value-of select="name" />
<xsl:text> (> 10M)</xsl:text>
<xsl:text> </xsl:text>
</xsl:template>
</xsl:stylesheet>
Output:
* Algeria (> 10M)
xsl:template match="/"
File: Data.xml
<?xml version="1.0" encoding="utf-8"?>
<data>
<element>Fe</element>
<element>Cl</element>
<element>Br</element>
<element>I</element>
<element>Ni</element>
<element>H</element>
<element>Po</element>
<element>S</element>
<element>O</element>
</data>
File: Transform.xslt
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:copy/>
</xsl:template>
</xsl:stylesheet>