You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何非#default模式下text()会被XSL模板匹配并输出?

XSLT 模板匹配异常原因解析

问题场景

给定XML文档:

<?xml version="1.0" encoding="utf-8" ?>
<x>
  <y>test</y>
</x>

对应的XSL样式表:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:template match="/x">
    <xsl:copy>
      <xsl:apply-templates select="//y" mode="foo"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="node()|@*" mode="#default">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

用户预期输出为 <x/>,认为第二个模板会处理 <y> 元素,但实际得到的输出是 <x>test</x>,下面解释该现象的核心原因。

原因拆解

问题本质出在模板匹配模式和XSLT的内置模板规则上:

  • 第一个模板匹配<x>节点时,调用<xsl:apply-templates select="//y" mode="foo"/>给<y>指定了foo模式。
  • 你写的第二个模板明确标记了mode="#default",也就是只处理默认模式下的节点,对带foo模式的<y>完全不生效。
  • 当XSLT找不到对应foo模式的模板时,会触发内置的默认模板规则:
    • 遇到元素节点(比如<y>),内置模板会自动处理它的子节点(这里就是文本test);
    • 遇到文本节点,内置模板直接输出文本内容。
  • 最终<y>的文本子节点test被输出到<x>标签内,得到<x>test</x>。

如果要得到预期的<x/>,只需添加一个匹配foo模式的空模板,让<y>被匹配后不做任何输出:

<xsl:template match="*" mode="foo"/>

内容的提问来源于stack exchange,提问作者yegor256

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 00:18:19