XSLT如何调用模板?

来源:网络编程作者:森沢头衔:网络博主
导读:本期聚焦于小伙伴创作的《XSLT如何调用模板?》,敬请观看详情。当XML文档结构复杂、节点层级深时,单纯用匹配规则很难理清输出逻辑。XSLT提供的模板机制把每个节点的处理拆成独立单元,再通过特定指令把控制权交给对应模板。理解xsl:template的定义方式与xsl:apply-templates的遍历逻辑,是写出可维护转换样式的核心。本文说明两种调用路径:一是用apply-templates按选中节点自动匹配,二是用call-template显式点名调用。我们会结合带参数的例子展示如何传递数据、如何设置默认模式,并对比二者在复用性与执行顺序上的差别,帮助你在实际报表或接口报文转换中少走弯路。

XSLT(可扩展样式表转换语言)把XML转换成HTML、文本或其他XML时,核心思想是为不同类型的节点编写独立模板,再决定何时、以什么顺序去执行这些模板。所谓“调用模板”,就是指在转换过程中激活某个已定义的xsl:template规则。XSLT主要提供两条调用路径:一条是数据驱动的xsl:apply-templates,它会选中一组节点并自动寻找匹配模板;另一条是过程式的xsl:call-template,它像函数调用一样按名字直接执行模板。掌握二者的语义差异,才能避免嵌套混乱和重复输出。

XSLT如何调用模板?

一、用xsl:template定义可被调用的模板

在XSLT中,任何模板都必须先通过xsl:template元素声明。它有两个最常用的属性:match和name。match用来绑定某个XPath模式,当apply-templates选中的节点符合该模式时,模板被自动调用;name则给模板起一个标识符,供call-template按名调用。一个模板内部可以包含字面结果元素、XPath取值表达式以及其他调用指令。

下面示例定义了两个模板:第一个匹配book节点,输出书名;第二个按名字定义,用来统一输出价格格式。注意带name的模板本身不会自动执行,必须被其他模板显式或隐式调用。

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <!-- 匹配型模板 -->
  <xsl:template match="book">
    <div>
      <h3><xsl:value-of select="title"/></h3>
      <xsl:call-template name="show-price">
        <xsl:with-param name="val" select="price"/>
      </xsl:call-template>
    </div>
  </xsl:template>

  <!-- 命名模板,可被call-template调用 -->
  <xsl:template name="show-price">
    <xsl:param name="val" select="0"/>
    <p>价格:<xsl:value-of select="$val"/>元</p>
  </xsl:template>
</xsl:stylesheet>

上述代码中,book模板在处理每本书时,使用call-template指向show-price,并通过with-param传递当前节点的price值。xsl:param在命名模板中声明参数,select="0"表示若调用方未传值则使用默认值。这种结构让价格展示逻辑只写一次,达到复用效果。

二、xsl:apply-templates的数据驱动调用

xsl:apply-templates是XSLT中最具特色的调用方式。它不改变XML节点顺序,而是对当前上下文中的被选节点依次查找最佳匹配的模板。如果不写select属性,默认处理当前节点的所有子节点。这种方式适合树状结构的递归转换,例如把目录树转成嵌套列表。

以下例子展示如何用apply-templates遍历员工列表,并为每个employee节点匹配不同模板。根模板先选中所有employee,处理器会为每个节点寻找match="employee"的模板;若该模板内部再写apply-templates,就会继续向下层展开,形成自动递归。

<xsl:template match="/">
  <ul>
    <xsl:apply-templates select="company/employee"/>
  </ul>
</xsl:template>

<xsl:template match="employee">
  <li>
    <xsl:value-of select="name"/>
    <xsl:apply-templates select="skill"/>
  </li>
</xsl:template>

<xsl:template match="skill">
  <em>(擅长:<xsl:value-of select="."/>)</em>
</xsl:template>

使用apply-templates时,若多个模板都能匹配同一节点,XSLT会按优先级和导入顺序选择最具体的那一个。它的优势在于松耦合:新增节点类型只需补一个match模板,调用方无需修改。缺点是执行顺序依赖文档结构,不太适合需要严格步骤控制的场景。

三、xsl:call-template的显式调用

与apply-templates相反,call-template完全按编写者指定的名字调用,不会去做节点匹配。它更像传统编程语言里的函数调用,因此执行顺序清晰、可控。当某段逻辑与具体节点无关,或者需要在不同位置反复插入相同输出时,命名模板加call-template是最直接的选择。

下面的示例定义一个格式化日期的命名模板,在表头和详情两处分别调用,保证格式统一。由于call-template不依赖上下文节点,我们可以在任意模板中传入不同参数来复用它。

<xsl:template name="format-date">
  <xsl:param name="d"/>
  <xsl:value-of select="substring($d,1,4)"/>年
  <xsl:value-of select="substring($d,6,2)"/>月
</xsl:template>

<xsl:template match="report">
  <header>
    <xsl:call-template name="format-date">
      <xsl:with-param name="d" select="@gen"/>
    </xsl:call-template>
  </header>
  <xsl:apply-templates select="item"/>
</xsl:template>

call-template的局限在于它把调用关系硬编码在样式表里,一旦命名模板改名,所有调用点都要同步修改。另外它不会自动遍历子节点,若需要递归处理树结构,仍要配合apply-templates或自身递归调用。

四、两种调用方式对比与选用建议

从设计意图看,apply-templates强调“数据说什么就处理什么”,适合把未知或易变的XML结构映射成目标格式;call-template强调“我要做什么”,适合固定流程与公共片段。实际项目中二者常常混用:用apply-templates搭建主干遍历,用call-template抽取公共展示块。

下表归纳了主要差异,方便在编码时快速判断:

对比维度xsl:apply-templatesxsl:call-template
调用依据节点匹配match模式模板name名字
执行顺序由源文档节点顺序决定由样式表编写位置决定
参数传递通过当前节点上下文隐式提供用with-param显式传参
适用场景树状递归、结构映射公共片段、固定步骤

建议初学者先写几个match模板体会apply-templates的自动分发,再把重复代码抽成name模板用call-template调用。当转换规则超过两百行时,这种混合模式能显著降低维护成本。最后提醒,模板中若同时出现两种调用,注意避免无限递归,例如一个命名模板内部call自身却无退出条件,会导致转换器堆栈溢出。

XSLTtemplatexsl_apply_templates修改时间:2026-08-06 22:51:58

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。