XML Tutorial/XSLT stylesheet/template

Материал из Web эксперт
Перейти к: навигация, поиск

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 &lt;= $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 &lt; $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 &lt;= 10000000]">
    <xsl:text> * </xsl:text>
    <xsl:value-of select="name" />
    <xsl:text> (&lt;= 10M)</xsl:text>
    <xsl:text>&#10;</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>&#10;</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>