You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@xalan.apache.org by Steve Dunham <du...@cse.msu.edu> on 2000/12/05 03:29:20 UTC

A note on using parameters to pass information between templates


I saw a few questions in my overflowing xalan-dev mailbox about
variables, and thought I'd leave a few hints on how I've used them
recursively to pass along information.  This is probably old hat for
the experts out there, but may be useful to XSLT beginners.


Reading the XSLT spec, you'll see that variables and parameters can be
set once within a template.  Also, they have lexical scoping.  If you
change a variable and just call another template, it won't see your
change.


To pass a parameter to another template you have to have a
<xsl:with-param> inside the <xsl:apply-templates>.  I've also found
that it helps to declare the variable at the top level, so you don't
get errors from your transformer.

So, if you wanted to process something like:

<top>
  <foo idref="xyzzy"><info>Something</info></foo>
  <templates>
    <bar idatt="xyzzy">
      <some>tags<and><i/></and>stuff</some>
    </bar>
  </templates>
</top>

Into

<top>
  <some>tags<and><info>Something</info></and>stuff</some>
</top>

(A template expansion example.)  You want to call process the template
"bar" recursively, and pass it a value; you can use xsl:with-param to
do the trick, but you have to make sure you pass it explicitly through
every apply-templates that you do:

<xsl:stylesheet ...>
  <xsl:param name="info" value="whatever/>
  
  <xsl:template match="templates"/> <!-- delete templates from output -->

  <xsl:template match="foo">
    <xsl:variable name="id" select="@idref"/>
    <xsl:apply-templates select="//bar[@idatt=$id]">
      <xsl:with-param name="info" value="inforec"/>
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="i">
    <xsl:apply-templates select="$info"/>
  </xsl:template>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()">
        <xsl:with-param name="info" select="$info"/>
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>


Note that every time we recurse, we have to explicitly pass the
parameter in our apply-templates.  (The last template is just a match
everything copy template with our parameter passing added.)


Steve
dunham@cse.msu.edu