How Does Parameter Passing Work in XSLT?
Parameter passing in XSLT enables modular, reusable stylesheet design
by allowing templates to accept dynamic inputs. This article covers how
<xsl:param> declares receiving parameters inside
templates or at the stylesheet level, how
<xsl:with-param> supplies arguments during template
invocations via <xsl:call-template> and
<xsl:apply-templates>, and the rules governing
parameter scope, default values, and tunnel parameters.
Core Concepts: Declarations vs. Arguments
XSLT separates parameter mechanics into two distinct elements:
<xsl:param>(The Receiver): Declares a parameter and sets an optional default value. It can be placed at the stylesheet level (global parameter) or as a direct child of<xsl:template>(local template parameter).<xsl:with-param>(The Sender): Supplies a specific value to a template when invoking it with either<xsl:call-template>or<xsl:apply-templates>.
The XSLT processor maps values between the sender and receiver using
the mandatory name attribute matching on both elements.
Declaring Parameters with
<xsl:param>
When defining parameters inside a template, every
<xsl:param> element must appear as an immediate child
of <xsl:template> and must be placed before any other
instruction or output elements.
<xsl:template name="format-price">
<!-- Parameter declaration with a default value -->
<xsl:param name="amount" select="0.00" />
<xsl:param name="currency" select="'USD'" />
<span class="price">
<xsl:value-of select="$amount" />
<xsl:text> </xsl:text>
<xsl:value-of select="$currency" />
</span>
</xsl:template>If the calling template does not provide a parameter value via
<xsl:with-param>, the template falls back to the
default value defined in the select attribute or the body
of <xsl:param>.
Passing Values with
<xsl:with-param>
To supply values during a template call, nest
<xsl:with-param> elements inside the invocation
tag.
1. Named Template Calls
(<xsl:call-template>)
Named templates behave similarly to standard functions in procedural programming:
<xsl:template match="product">
<xsl:call-template name="format-price">
<xsl:with-param name="amount" select="price" />
<xsl:with-param name="currency" select="'EUR'" />
</xsl:call-template>
</xsl:template>2. Rule-Based
Template Calls (<xsl:apply-templates>)
When processing nodes matching specific patterns,
<xsl:with-param> passes the value down to matching
rule templates:
<xsl:template match="catalog">
<div class="product-list">
<xsl:apply-templates select="item">
<xsl:with-param name="discount-rate" select="0.15" />
</xsl:apply-templates>
</div>
</xsl:template>
<xsl:template match="item">
<xsl:param name="discount-rate" select="0.0" />
<p>
<xsl:value-of select="name" />:
<xsl:value-of select="price * (1 - $discount-rate)" />
</p>
</xsl:template>Parameter Scoping and Tunneling
Understanding scope and propagation prevents common transformation errors:
- Scope Boundaries: Parameters passed via standard
<xsl:with-param>apply only to the directly invoked template. They do not automatically cascade to downstream templates invoked within the callee. - Global Parameters:
<xsl:param>elements declared at the top level of the stylesheet (direct children of<xsl:stylesheet>) are accessible globally across all templates unless shadowed by a local parameter of the same name. - Tunnel Parameters (XSLT 2.0+): Setting
tunnel="yes"on both<xsl:with-param>and<xsl:param>allows a parameter to pass transparently through intermediate templates without requiring each intermediate template to declare and re-pass it.
Key Rules to Remember
- In XSLT 1.0,
<xsl:param>children must strictly precede all other instructions within<xsl:template>. - Parameter references in XPath expressions always require the
$prefix (e.g.,$amount). - Passing a parameter with a name that is not declared in the target template is ignored in XSLT 1.0, but may cause an error or warning in modern XSLT 2.0/3.0 processors unless tunnel parameters are used.