导读:本期聚焦于小伙伴创作的《XSLT中的模式(mode)是什么?如何对同一节点应用不同模板?》,敬请观看详情。一份XML数据往往需要同时生成多种视图,比如既要在页面中渲染完整正文,又要为侧边栏提取目录项。XSLT如何对同一个节点应用完全不同的两套模板?模式正是解决这类问题的关键机制。通过在xsl:template和xsl:apply-templates上同时指定mode属性,处理器能够把同一次节点选择分流到不同处理流程。无模式模板只响应不带mode的调用,而命名模式之间相互隔离,不会彼此干扰。这种设计让开发者可以在不修改源XML、不复制数据结构的前提下为相同元素编写多组规则,分别负责摘要、目录、打印版式或移动端视图。理解mode的匹配规则、默认模式以及内置规则,有助于简化复杂的XSLT转换逻辑。

在XSLT的转换流程中,模板匹配由match属性决定,而mode属性则负责把匹配结果进一步分流。对于同一个源节点,不同mode可以绑定不同的模板规则,让处理器按照调用方指定的模式输出完全不同的结构。例如章节节点既可以被渲染成完整正文,也可以仅提取标题生成目录,这种能力能够在不改动XML结构的前提下实现多视图输出。

XSLT中的模式(mode)是什么?如何对同一节点应用不同模板?

mode的基本概念与匹配规则

模式是 <xsl:template> 元素和 <xsl:apply-templates> 元素上的一个可选属性。它相当于给模板打上命名标记,只有带相同mode的调用才能触发该模板。没有指定mode的模板属于默认模式,只有不带mode的调用才会匹配它们。换句话说,mode把模板库划分成了多个相互隔离的命名空间,不同mode下的规则彼此不会串扰。

例如下面的样式表中针对同一个chapter节点声明了两套模板。第一套带有 mode="toc",负责输出列表项;第二套没有mode,负责输出完整章节内容。两者虽然匹配同一个节点,却分别在不同的调用路径下生效。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" encoding="UTF-8"/>
  <xsl:template match="chapter" mode="toc">
    <li><xsl:value-of select="title"/></li>
  </xsl:template>
  <xsl:template match="chapter">
    <section>
      <h2><xsl:value-of select="title"/></h2>
      <p><xsl:value-of select="para"/></p>
    </section>
  </xsl:template>
</xsl:stylesheet>

处理器在选择模板时,会先根据 <xsl:apply-templates> 的select表达式选取节点,再比较mode标记。如果调用没有写mode,那么带mode的模板不会参与匹配;如果调用写的是 mode="toc",那么默认模式下的模板也不会被选中。这种隔离机制避免了同一组节点在多路输出时发生模板覆盖或冲突。

如何对同一节点应用不同模板

要理解mode的核心价值,最好的方式是一次转换中对同一批节点执行两次不同模式的调用。下面这段样式表输入一个商品目录,同一组item节点先被 mode="list" 处理成列表项,随后又被 mode="detail" 处理成带价格信息的详情块。源XML如下。

<?xml version="1.0" encoding="UTF-8"?>
<catalog>
  <item sku="1001">
    <name>机械键盘</name>
    <price>399</price>
  </item>
  <item sku="1002">
    <name>无线鼠标</name>
    <price>159</price>
  </item>
</catalog>

对应的XSLT样式表如下。根模板中第一次调用 <xsl:apply-templates select="catalog/item" mode="list"/>,只触发 list 模式下的item模板;第二次调用 <xsl:apply-templates select="catalog/item" mode="detail"/>,则触发 detail 模式下的item模板。两次选择的节点完全相同,但输出结构完全不同。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" encoding="UTF-8"/>
  <xsl:template match="/">
    <html>
      <body>
        <ul>
          <xsl:apply-templates select="catalog/item" mode="list"/>
        </ul>
        <hr/>
        <xsl:apply-templates select="catalog/item" mode="detail"/>
      </body>
    </html>
  </xsl:template>
  <xsl:template match="item" mode="list">
    <li><xsl:value-of select="name"/></li>
  </xsl:template>
  <xsl:template match="item" mode="detail">
    <div>
      <h3><xsl:value-of select="name"/></h3>
      <span><xsl:value-of select="price"/></span>
    </div>
  </xsl:template>
</xsl:stylesheet>

如果没有mode,两个同时匹配item节点的模板会形成冲突,XSLT 1.0处理器通常会报错,因为同一节点匹配到多个具有相同默认优先级的模板。而引入mode之后,两个模板分别属于 list 和 detail 两个模式,它们之间不再直接竞争。这样就能安全地保留多种处理逻辑。

需要注意的是,<xsl:apply-templates> 上的mode必须与 <xsl:template> 上的mode严格对应。如果调用指定了 mode="list",但样式表中没有任何模板声明该mode,处理器不会退回使用无mode模板,而是按照该模式下的内置规则继续处理子节点。这种静默行为有时会让输出明显缺失,因此调试多模式样式表时,应当逐个确认调用与模板声明是否成对出现。

命名模式的实际应用场景

mode并不是只用于演示的小工具,它在实际项目中的价值非常突出。一个典型的场景是文档发布系统:源XML中包含大量章节和段落,网站既需要生成完整正文,又需要生成站内目录。目录通常只需要章节标题,而正文需要标题、段落、图片、列表等全部内容。使用 mode="toc"

XSLTmodeapply-templates修改时间:2026-08-13 02:59:09

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