5

这是一个简单的案例。

这是我的 XML:

<?xml version="1.0" encoding="utf-8" ?>
<dogs>
    <dog type="Labrador">
        <Name>Doggy</Name>
    </dog>
    <dog type="Batard">
        <Name>Unknown</Name>
    </dog>
</dogs>

此 XML 与两个 Xslt 一起使用。这是常见的:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
    <xsl:output method="text"/>

    <xsl:template match="dogs">
        <xsl:text>First template&#13;&#10;</xsl:text>
        <xsl:apply-templates select="." mode="othertemplate" />
    </xsl:template>
</xsl:stylesheet>

这是孩子一号:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
    <xsl:include href="transform.xslt"/>

    <xsl:template match="dogs" mode="othertemplate">
        <xsl:text>&#9;&#9;Other template</xsl:text>
    </xsl:template>
</xsl:stylesheet>

孩子包括共同的(称为transform.xslt)。

当我执行孩子时,我得到了预期的结果:

First template
        Other template

当我执行常见的,我得到这个奇怪的结果:

First template


        Doggy


        Unknown

常见的应用模式为“othertemplate”的模板。有时,此模式仅包含在子 xslt 中。

我想要那个,如果没有模式为“othertemplate”的模板,那么什么都不应该输出。

我不想为所有不必使用此模板模式的 xslt 文件包含模式为“othertemplate”且正文为空的模板...

我该怎么办?

谢谢

4

2 回答 2

10

XSLT 中的内置模板规则

由于 XSLT 的内置模板规则(也称为默认模板),会出现元素内容和额外的空格。当没有其他匹配模板时应用这些规则。内置模板规则是

<xsl:template match="*|/">
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="text()|@*">
  <xsl:value-of select="."/>
</xsl:template>

<xsl:template match="processing-instruction()|comment()"/>

内置模板规则递归处理根节点和元素节点并复制文本(如果选择了属性节点,则复制属性值)。处理指令和注释的内置模板规则是什么都不做。默认情况下不处理命名空间节点。请注意,这<xsl:apply-templates/>实际上是一种简写,<xsl:apply-templates select="child::node()"/>因此它不会选择属性或命名空间节点。

每种模式还有一个内置的模板规则。这些模板类似于元素和根的默认模板,只是它们继续以相同的模式进行处理。

<xsl:template match="*|/" mode="foobar">
  <xsl:apply-templates mode="foobar"/>
</xsl:template>

因为您的样式表没有dogs与模式匹配othertemplate的模板,所以应用了这个内置的模板规则,在这种情况下会导致处理所有子节点并最终打印文本节点。源文档元素之间的缩进和换行也是文本节点,因此它们也会被打印并导致输出中出现额外的空白。

警告非终止循环,因为<xsl:apply-templates select="."/>

通常apply-templates用于处理后代。在您的示例代码中,您在调用时选择了当前节点apply-templatesapply-templates如果模板本身由于其中的命令而被应用,这可能会导致非终止循环。下面的例子

<xsl:template match="foobar">
  <!-- This is an infinite loop -->
  <xsl:apply-templates select="."/>
</xsl:template>

顺便一提。关于组合样式表的一般规则,请仔细考虑应该运行哪个模板以及应该导入或包含哪个模板。(我已经读过,作为一般做法,Michael Kay 似乎建议使用<xsl:import>将一般情况样式表导入特殊情况样式表,而不是相反。)

于 2010-08-26T18:39:37.553 回答
6

为每种模式定义和选择了内置 XSLT 模板。因此,文本节点的内置模板被选中,并且(根据定义)它输出文本节点。

为了抑制这种情况,您需要在所需模式下使用空模板覆盖文本节点(也可能用于元素)的内置模板:

<xsl:template match="text()" mode="othertemplate"/>

在您导入的样式表中包含以上内容

于 2010-08-26T18:40:39.440 回答