Passing Parameters Using Named Templates
The following might be a first attempt at a template rule to produce a company-wide quarterly sales report.
<xsl:template match="sales"> <h1>Quarterly Sales by Region</h1> <h2>Quarter Beginning <xsl:value-of select="@quarter"/></h2> <xsl:apply-templates/> <h3>Company-Wide Results</h3> <table width="100%"> <xsl:call-template name="common_table"/><tr>
<td width="33%" align="right">
<xsl:value-of select="format-number(sum(region/units), '#,##0')"/>
</td>
<td width="33%" align="right">
<xsl:value-of select="format-number(sum(region/sales_amt), '#,##0.00')"/>
</td>
<td align="right">
<xsl:value-of select="format-number(sum(region/sales_amt) div sum(region/units), '#,##0.000')"/>
</td>
</tr>
</table>
</xsl:template>
Notice that this looks very similar to a template rule for an individual sales region. The only differences between this template rule and the one for the <region>
element are the data values being plugged into the table. Even the surrounding <table>
element is the same, and the level-3 headings that precede the tables differ only in their contents.
Fortunately, XSLT supplies parameters. Parameters enable you to pass values into a named template to be inserted as needed into a common format.
Parameters are passed from the calling template rule to the named template by <xsl:with-param>
elements in the template rule, and by <xsl:param>
elements in the named template. Each <xsl:with-param>
element is a child of the <xsl:call-template>
element. Each <xsl:param>
element is a child of the named template's <xsl:template>
element.
For example, a named template to be passed a parameter might look like this:
<xsl:template name="param_template"> <xsl:param name="passed_param
"/> <h1><xsl:value-of select="$passed_param
"/></h1> </xsl:template>
The following might be a template rule to pass data to this named template.
<xsl:template match="/">
<xsl:call-template name="param_template">
<xsl:with-param name="passed_param
>
Our Company Name</xsl:with-param>
</xsl:call-template>
</xsl:template>
This template rule passes the string "Our Company Name
" to the param_template
named template by way of the passed_param
parameter. The passed value is then inserted into an <h1>
element by the named template, and instantiated in the result tree of the template rule.
The <xsl:with-param>
and <xsl:param>
elements also have an optional select
attribute. In the calling template rule, the value of this attribute is an XPath expression relative to the context node at that point. For more information about context nodes, see Determining the Context Node. In the named template, the select
attribute of the <xsl:param>
element supplies a default value if a calling template rule fails to provide one.
Therefore, we can now change our named template as follows. In particular, note the use of passed parameters substituted into the common table structure.
<xsl:template name="common_table"><xsl:param name="table_hdg" select="'Default Heading'"/>
<xsl:param name="units_param" select="'Default Units'"/>
<xsl:param name="amt_param" select="'Default Amount'"/>
<h3><xsl:value-of select="$table_hdg
"/></h3> <table width="100%"> <tr> <th width="33%"># Units</th> <th width="33%">Qtr Sales Amount</th> <th>Amt/Unit</th> </tr> <tr> <td width="33%" align="right"> <xsl:value-of select="format-number($units_param
, '#,##0')"/> </td> <td width="33%" align="right"> <xsl:value-of select="format-number($amt_param
, '#,##0.00')"/> </td> <td align="right"> <xsl:value-of select="format-number($amt_param
div$units_param
, '#,##0.000')"/> </td> </tr> </table> </xsl:template>
The template rules for the <sales>
and <region>
elements are now shorter, as follows:
<xsl:template match="sales"> <h1>Quarterly Sales by Region</h1> <h2>Quarter Beginning <xsl:value-of select="@quarter"/></h2> <xsl:apply-templates/> <xsl:call-template name="common_table"><xsl:with-param name="table_hdg" select="'Company-Wide Results'"/>
<xsl:with-param name="units_param" select="sum(region/units)"/>
<xsl:with-param name="amt_param" select="sum(region/sales_amt)"/>
</xsl:call-template> </xsl:template> <xsl:template match="region"> <xsl:call-template name="common_table"><xsl:with-param name="table_hdg">
<xsl:value-of select="name"/> Region
(Manager: <xsl:value-of select="manager"/>)
</xsl:with-param>
<xsl:with-param name="units_param" select="units"/>
<xsl:with-param name="amt_param" select="sales_amt"/>
</xsl:call-template> </xsl:template>
Note When passing string values to named templates, be sure to enclose the string value in internal quotation marks. For example, in theselect
attribute of the<xsl:with-param name="table_hdg" select="'Company-Wide Results'"/>
code in the<sales>
template rule above,"Company-Wide Results"
(without internal quotation marks) would be incorrect. If you omit the internal quotation marks, the XPath expression is evaluated as if it refers to a child of the context node at that point.
Although this example simply passes parameters for display, note that you can also use parameters to control optional processing in the named template. For example, we could use parameters to insert some extra spacing and a horizontal rule into the named template, to be displayed immediately before the company-wide results. The following code does this with an <xsl:if>
element with a $table_hdg
parameter.
<xsl:if test="$table_hdg
='Company-Wide Results'">
<p />
<hr />
</xsl:if>
The resulting finished example is shown in the next topic, Finished Example for Named Templates.