在XML数据转换任务中,XSLT提供了一套基于规则的处理模型。其中template用来声明“当碰到某种节点时应该怎么做”,而apply-templates负责“继续往下走,把子节点交给合适的template处理”。二者构成一种拉取加推送的混合机制:样式表作者写好若干template,再由apply-templates在树中漫游并触发它们。缺少任何一半,转换结果都会不完整或失去结构。

template的基本结构与匹配规则
一个template通过match属性指定它要处理的节点模式,可以是元素名、路径或谓词表达式。当XSLT处理器遇到节点且存在匹配的template时,就会执行该template体内的指令。如果没有显式匹配,处理器会使用内置的默认template,例如对文本节点原样输出、对元素节点继续向下应用模板。
下面是一段最基础的template示例,它将book元素转换为HTML段落,并输出书名。注意这里使用了select在value-of中定位子节点,但并没有主动处理book以外的结构。
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="book">
<p>
<xsl:value-of select="title"/>
</p>
</xsl:template>
</xsl:stylesheet>
当多个template都能匹配同一个节点时,处理器依据优先级和导入顺序选择最具体的那一个。例如match="book"比match="*"更具体,因此前者优先。利用这种机制,我们可以为不同层级的元素定制输出,而不必在一个巨大的template里写满条件判断。
apply-templates如何驱动节点遍历
apply-templates的作用是从当前节点出发,选取一部分子节点(通过select)并依次寻找匹配的template。如果不写select,则默认处理所有子节点。它本质上把控制权交还给处理器,让其继续递归,这正是XSLT声明式风格的核心:你描述“做什么”,遍历由引擎完成。
在根节点template中调用apply-templates,才能启动整棵树的转换。以下示例展示了从根开始,把每个book交给上面的template,同时忽略其他节点:
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates select="library/book"/>
</body>
</html>
</xsl:template>
如果去掉apply-templates,根template只输出静态HTML,动态内容全部丢失。另一方面,在book的template内部也可以再次调用apply-templates来处理title或author,从而把结构层层展开。这种递归调用让复杂文档的转换保持清晰,每个template只关心自己那一层。
使用mode与select解决重复和筛选问题
实际项目中,同一个元素可能需要在不同位置以不同形式出现,例如目录区和详情区都要渲染book。此时可以用mode属性给template分组,apply-templates通过相同mode只触发对应组的template,避免互相干扰。
下面的代码演示了两种mode:摘要模式只输出标题,详情模式输出完整信息。调用方明确指定mode,处理器就不会找错template。
<xsl:template match="book" mode="summary">
<li><xsl:value-of select="title"/></li>
</xsl:template>
<xsl:template match="book" mode="detail">
<div>
<h3><xsl:value-of select="title"/></h3>
<p>作者:<xsl:value-of select="author"/></p>
</div>
</xsl:template>
<xsl:template match="/">
<ul><xsl:apply-templates select="library/book" mode="summary"/></ul>
<xsl:apply-templates select="library/book" mode="detail"/>
</xsl:template>
除了mode,select还能配合XPath过滤,比如只处理价格高于30的book:select="library/book[price > 30]"。这种声明式筛选比在template里写if更直观,也更容易维护。掌握template与apply-templates的协作方式后,就能把任意XML结构稳妥地映射为目标格式,而不陷入命令式循环的琐碎之中。
XSLTtemplateapply-templates修改时间:2026-08-16 20:26:29