为什么以前的代码输出TEXT,为什么我要坚持XSL忽略所有其他文本?是所有XML解析器的行为还是我自己的行为
您将发现规范中指定的最基本的XSLT功能之一:XSLT的内置模板。
从规格:
有一个内置的模板规则,允许样式表中的显式模板规则在没有成功的模式匹配的情况下继续进行递归处理。此模板规则适用于元素节点和根节点。下面显示了等效的内置模板规则:
<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>
用于处理指令和注释的内置模板规则不执行任何操作。
<xsl:template match="processing-instruction()|comment()"/>
命名空间节点的内置模板规则也不执行任何操作。没有可以匹配名称空间节点的模式。因此,内置模板规则是应用于名称空间节点的唯一模板规则。
内置模板规则被视为好像是在样式表之前隐式导入的,因此其导入优先级低于所有其他模板规则。因此,作者可以通过包含显式模板规则来覆盖内置模板规则。
因此,报告的行为是应用内置模板的结果-所有三个模板中的第一个和第二个。
一个很好的XSLT设计模式是用您自己的模板覆盖内置模板,该模板每次被调用时都会发出错误消息,以便程序员立即知道他的转换是“泄漏的”:
例如,如果有此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"/>
产生警告。