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:

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:

Key Rules to Remember

  1. In XSLT 1.0, <xsl:param> children must strictly precede all other instructions within <xsl:template>.
  2. Parameter references in XPath expressions always require the $ prefix (e.g., $amount).
  3. 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.