为什么之前的代码输出的是TEXT,
为什么我要坚持 XSL 忽略所有
其他文字?那是
所有的 XML 解析器或只有我自己的
您正在发现规范中指定的最基本的 XSLT 功能之一:built-in templates of XSLT。
来自the Spec:
有一个内置的模板规则
允许递归处理继续
在没有成功模式的情况下
通过显式模板规则匹配
样式表。此模板规则
适用于元素节点和
根节点。下面显示了
相当于内置模板
规则:
<xsl:template match="*|/">
<xsl:apply-templates/>
</xsl:template>
还有一个内置的模板规则
对于每种模式,它允许递归
处理以继续相同
在没有成功的模式下
通过显式模板进行模式匹配
样式表中的规则。这个模板
规则适用于元素节点和
根节点。下面显示了
相当于内置模板
模式 m 的规则。
<xsl:template match="*|/" mode="m">
<xsl:apply-templates mode="m"/>
</xsl:template>
还有一个内置的模板规则
对于文本和属性节点
通过以下方式复制文本:
<xsl:template match="text()|@*">
<xsl:value-of select="."/>
</xsl:template>
内置模板规则
处理指令和 cmets
就是什么都不做。
<xsl:template match="processing-instruction()|comment()"/>
内置模板规则
命名空间节点也是什么都不做。
没有模式可以匹配
命名空间节点;所以,内置
模板规则是唯一的模板
应用于命名空间的规则
节点。
内置的模板规则是
被视为进口的
隐式在样式表之前和
所以进口优先级低于
所有其他模板规则。就这样
作者可以覆盖内置
通过包含显式的模板规则
模板规则。
因此,报告的行为是应用内置模板的结果——这三个模板中的第一个和第二个。
用您自己的模板覆盖内置模板是一种很好的 XSLT 设计模式,每当调用时都会发出错误消息,以便程序员立即知道他的转换正在“泄漏”: p>
例如,如果有这个XML文档:
<a>
<b>
<c>Don't want to see this</c>
</b>
</a>
并使用此转换进行处理:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="a|b">
<xsl:copy>
<xsl:attribute name="name">
<xsl:value-of select="name()"/>
</xsl:attribute>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
结果是:
<a name="a">
<b name="b">Don't want to see this</b>
</a>
程序员会很困惑不想要的文本是如何出现的。
但是,只需添加此 catch-all template 有助于避免任何此类混淆并立即捕获错误:
<xsl:template match="*">
<xsl:message terminate="no">
WARNING: Unmatched element: <xsl:value-of select="name()"/>
</xsl:message>
<xsl:apply-templates/>
</xsl:template>
现在,除了令人困惑的输出之外,程序员会收到一个警告,立即解释问题:
WARNING: Unmatched element: c
Michael Kay 之后为 XSLT 3.0 添加的内容
在 XSLT 3.0 中,您可以在 xsl:mode 声明中指定回退行为,而不是添加包罗万象的模板规则。例如,<xsl:mode on-no-match="shallow-skip"/> 导致所有不匹配的节点(包括文本节点)被跳过,而<xsl:mode on-no-match="fail"/> 将不匹配视为错误,<xsl:mode warning-on-no-match="true"/> 导致警告。