为何在XSLT中使用mode属性会输出整个XML原始文本?
XSLT mode与name模板输出差异问题解析
问题本质:mode和name的核心功能完全不同
你误以为name和mode功能相近,其实两者定位完全不一样:
- name属性:只是给模板起个标识名,方便用
<xsl:call-template>直接调用,但它不改变模板的匹配逻辑——只要节点符合match规则,处理器在常规(无指定mode)的模板处理流程中,依然会选中这个模板。你用name="xyz"时,<Parent>节点被匹配到该模板,所以输出预期的结构。 - mode属性:是给模板标记一个“模式”,只有当你通过
<xsl:apply-templates mode="xyz">主动调用时,这个模板才会生效。如果没有触发对应模式的调用,处理器会执行XSLT的内置默认模板,这就是你看到原始文本的原因。
为什么mode模板会输出原始文本?
你的mode="xyz"模板没有被触发,因为处理器默认是按“无模式”的方式遍历节点:
- 处理器从根节点开始,找不到匹配根节点的自定义模板,就用默认模板处理根节点的子节点(也就是
<Parent>) - 处理
<Parent>时,因为没有无模式的自定义模板(你的模板只属于xyz模式),所以再次用默认模板处理<Parent>的子节点:<ParentCon>、<Child> - 默认模板处理元素节点时,会递归处理其所有子节点;处理文本节点时,直接输出文本内容。最终所有文本节点(Parent Content、Child Content、Some Grandchild Content)被输出,就得到了你看到的无标记原始文本。
解决方案:让mode模板生效
要让带mode的模板正常工作,需要显式在主模板中触发对应模式的模板调用:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 处理根节点的主模板,触发mode=xyz的模板 --> <xsl:template match="/"> <xsl:apply-templates select="Parent" mode="xyz"/> </xsl:template> <xsl:template match="Parent" mode="xyz"> <ExportParent> <ExportChild/> </ExportParent> </xsl:template> </xsl:stylesheet>
如果希望模板同时支持无模式和指定模式调用(XSLT 2.0及以上版本可用),可以给mode设置多个值:
<xsl:template match="Parent" mode="#default xyz"> <ExportParent> <ExportChild/> </ExportParent> </xsl:template>
这样无论是否指定mode,<Parent>节点都会匹配到这个模板,输出预期结果。
内容的提问来源于stack exchange,提问作者Dragyn
相关产品推荐
相关产品推荐

