XSLT中的变量和参数是用于临时存储数据、实现动态转换逻辑的重要特性,二者都能在转换过程中保存数据供后续使用,但适用场景和作用域有明显区别。

XSLT变量的定义与使用
变量的基本概念
XSLT变量用于在转换过程中存储临时数据,比如某个节点的计算结果、重复使用的字符串等。变量一旦定义之后,在作用域内是不可修改的,属于只读属性。
变量的定义语法
变量使用<xsl:variable>标签定义,需要指定name属性作为变量名,值可以通过select属性指定,也可以在标签内部编写内容。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<!-- 通过select属性定义变量 -->
<xsl:variable name="book_count" select="count(//book)" />
<!-- 通过标签内部内容定义变量 -->
<xsl:variable name="greeting">
当前共有
</xsl:variable>
<p>
<xsl:value-of select="$greeting" />
<xsl:value-of select="$book_count" />
本书
</p>
</xsl:template>
</xsl:stylesheet>
变量的作用域
变量的作用域由定义它的位置决定:如果在模板内部定义,作用域就是当前模板;如果在样式表顶层定义,作用域是整个样式表。变量名前需要加$符号才能引用。
XSLT参数的定义与使用
参数的基本概念
参数是用于从外部接收传入值的特殊变量,通常在调用模板或者执行转换时由外部传入,适合需要动态适配不同场景的转换需求。
参数的定义语法
参数使用<xsl:param>标签定义,同样需要指定name属性,还可以设置select属性作为默认值,如果没有传入值就使用默认值。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- 定义全局参数,默认值为false -->
<xsl:param name="show_price" select="false()" />
<xsl:template match="/">
<xsl:apply-templates select="//book" />
</xsl:template>
<xsl:template match="book">
<div>
<p>书名:<xsl:value-of select="title" /></p>
<!-- 根据参数判断是否显示价格 -->
<xsl:if test="$show_price">
<p>价格:<xsl:value-of select="price" /></p>
</xsl:if>
</div>
</xsl:template>
</xsl:stylesheet>
参数的传入方式
如果是全局参数,可以在转换时由外部程序传入值,比如使用Java的XSLT处理器时,可以通过设置参数值覆盖默认值。如果是模板参数,可以在调用模板时使用<xsl:with-param>标签传入值。
<!-- 调用带参数的模板 -->
<xsl:call-template name="book_info">
<xsl:with-param name="show_author" select="true()" />
</xsl:call-template>
<!-- 定义带参数的模板 -->
<xsl:template name="book_info">
<xsl:param name="show_author" select="false()" />
<p>图书信息</p>
<xsl:if test="$show_author">
<p>作者:<xsl:value-of select="author" /></p>
</xsl:if>
</xsl:template>
变量和参数的核心区别
二者的主要差异如下:
| 对比项 | 变量 | 参数 |
|---|---|---|
| 定义标签 | <xsl:variable> | <xsl:param> |
| 值来源 | 内部定义或计算 | 外部传入或默认值 |
| 默认值 | 无默认值,必须指定值 | 可设置默认值 |
| 典型场景 | 存储临时计算结果 | 接收外部动态配置值 |
使用示例:结合变量和参数处理XML数据
以下是一个完整的示例,处理包含图书信息的XML,使用变量计算平均价格,使用参数控制是否显示库存信息。
<!-- 输入XML示例 -->
<bookstore>
<book>
<title>XSLT入门</title>
<price>59.9</price>
<stock>20</stock>
</book>
<book>
<title>XML进阶</title>
<price>69.9</price>
<stock>15</stock>
</book>
</bookstore>
<!-- XSLT转换文件 -->
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- 参数:是否显示库存 -->
<xsl:param name="show_stock" select="false()" />
<xsl:template match="/">
<!-- 变量:计算图书总数 -->
<xsl:variable name="total_books" select="count(bookstore/book)" />
<!-- 变量:计算总价格 -->
<xsl:variable name="total_price" select="sum(bookstore/book/price)" />
<!-- 变量:计算平均价格 -->
<xsl:variable name="avg_price" select="$total_price div $total_books" />
<h2>图书列表</h2>
<p>图书总数:<xsl:value-of select="$total_books" /></p>
<p>平均价格:<xsl:value-of select="format-number($avg_price, '0.00')" /></p>
<xsl:for-each select="bookstore/book">
<div style="margin-bottom:10px;">
<p>书名:<xsl:value-of select="title" /></p>
<p>价格:<xsl:value-of select="price" /></p>
<xsl:if test="$show_stock">
<p>库存:<xsl:value-of select="stock" /></p>
</xsl:if>
</div>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
通过这个示例可以看到,变量适合存储转换过程中需要重复使用的计算结果,参数适合让转换逻辑适配不同的外部需求,二者结合可以大幅提升XSLT转换的灵活性。