XSLT动态选择模板的核心是声明式匹配而非命令式跳转,通过match属性、mode模式、apply-templates的select筛选及test条件判断,精准控制节点匹配与处理逻辑。

XSLT 中通过 match 属性和 mode、apply-templates 的组合,配合 test 判断,就能实现按条件动态选择模板。核心不是“运行时切换模板名”,而是控制 <xsl:apply-templates> 匹配哪些节点、进入哪个模式、满足什么条件才触发。
用 select + test 精准投递节点
在 <xsl:apply-templates> 中用 select 显式指定要处理的节点,并结合 XPath 谓词过滤:
<xsl:apply-templates select="item[@status='active']"/> <xsl:apply-templates select="item[price > 100]"/> <xsl:apply-templates select="item[position() mod 2 = 1]"/>
这样只有符合条件的节点才会被送入模板匹配流程,自然就“动态选中”了对应 match="item" 的模板(或更具体的 match="item[@status='active']")。
用带条件的 match 模板优先匹配
定义多个 <xsl:template>,利用 XSLT 模板优先级规则(更具体的 match 优先):
<xsl:template match="item[@status='draft']"> <p class="draft"><xsl:value-of select="title"/>(草稿)</p> </xsl:template> <xsl:template match="item[@status='published']"> <article><xsl:value-of select="title"/></article> </xsl:template> <xsl:template match="item"> <div><xsl:value-of select="title"/></div> </xsl:template>
当 <xsl:apply-templates select="item"/> 执行时,XSLT 引擎会自动挑出最匹配的那个模板——无需手动判断,靠 match 表达式的 specificity 决定。
用 mode 隔离不同场景的处理逻辑
同一节点在不同上下文需不同输出?用 mode 分开定义,再按条件调用:
<xsl:template match="product">
<xsl:choose>
<xsl:when test="@featured = 'true'">
<xsl:apply-templates select="." mode="featured"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="." mode="list"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="product" mode="featured">
<section class="hero"><xsl:value-of select="name"/></section>
</xsl:template>
<xsl:template match="product" mode="list">
<li><xsl:value-of select="name"/></li>
</xsl:template>
mode 不改变节点本身,只提供“处理视角”的命名空间,让模板职责清晰、互不干扰。
用 <xsl:if> 或 <xsl:choose> 在模板内分支(慎用)
如果逻辑简单、仅局部差异,也可在单个模板里用条件指令:
<xsl:template match="user">
<div class="user">
<xsl:if test="age < 18">
<span class="minor">未成年</span>
</xsl:if>
<h3><xsl:value-of select="name"/></h3>
</div>
</xsl:template>
适合微调,但别把大量结构分支塞进一个模板——可读性和复用性会下降。优先用前三种方式做“模板级分发”。
基本上就这些。关键是理解:XSLT 的“动态选择”本质是声明式匹配,不是命令式跳转。写好 match、用好 select 和 mode,引擎自会按规则选对模板。










