Reputation: 37
I am trying to transform an XML document through a series of XSL stylesheets transformations in oXygen. I found the question Is daisy chaining xslt an accepted practice? and Dimitre Novatchev's answer (below) is great: it works perfectly as set out for two pass. I can't seem to get this to work for a third pass however.
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:variable name="vPass1" >
<xsl:apply-templates select="/*/*"/>
</xsl:variable>
<xsl:apply-templates mode="pass2"
select="$vPass1/*"/>
</xsl:template>
<xsl:template match="num[. mod 2 = 1]">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="num" mode="pass2">
<xsl:copy>
<xsl:value-of select=". *2"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
I've tried adding a second variable as below (in my problem I'm calling named templates instead of applying to the whole document). What I am calling template2 should be applied to the output of the transformation performed by template1.
Should I be declaring variable $vPass2 somewhere within template1 instead of in the same place as where i declare $vPass1? Or is there something else I'm not getting about how this works?
<xsl:template match="/">
<xsl:variable name="vPass1" >
<xsl:call-template name="template1"/>
</xsl:variable>
<xsl:apply-templates mode="pass2" select="$vPass1/*"/>
<xsl:variable name="vPass2" >
<xsl:call-template name="template2"/>
</xsl:variable>
<xsl:apply-templates mode="pass3" select="$vPass2/*"/>
</xsl:template>
Thanks
Upvotes: 2
Views: 1027
Reputation: 29042
When applying another step - here the third - you have to put the result of the second pass into a variable, too.
So, adding to the example from the linked answer, a three step solution could look like this:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:template match="/*">
<xsl:copy>
<xsl:variable name="vPass1">
<xsl:apply-templates select="/*/*" />
</xsl:variable>
<xsl:variable name="vPass2">
<xsl:apply-templates mode="pass2" select="$vPass1/*" />
</xsl:variable>
<xsl:variable name="vPass3">
<xsl:apply-templates mode="pass3" select="$vPass2/*" />
</xsl:variable>
<!-- Display the final result -->
<xsl:copy-of select="$vPass3"/>
</xsl:copy>
</xsl:template>
<xsl:template match="num[. mod 2 = 1]">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="num" mode="pass2">
<xsl:copy>
<xsl:value-of select=". *2"/>
</xsl:copy>
</xsl:template>
<xsl:template match="num" mode="pass3">
<xsl:copy>
<xsl:value-of select=". + 1"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Applied to this input XML
<nums>
<num>01</num>
<num>02</num>
<num>03</num>
<num>04</num>
<num>05</num>
<num>06</num>
<num>07</num>
<num>08</num>
<num>09</num>
<num>10</num>
</nums>
The result is (2*x+1)
<nums>
<num>3</num>
<num>7</num>
<num>11</num>
<num>15</num>
<num>19</num>
</nums>
Relating to your special question, your second <xsl:apply-templates mode="pass2" select="$vPass1/*"/>
is not in a variable - so its result will not be passed on to the third step.
Upvotes: 1