带模式的XSLT apply-template - 没有匹配模式的结果不正确

vIc*_*erg 5 xslt mode

这是一个简单的案例.

这是我的XML:

<?xml version="1.0" encoding="utf-8" ?>
<dogs>
    <dog type="Labrador">
        <Name>Doggy</Name>
    </dog>
    <dog type="Batard">
        <Name>Unknown</Name>
    </dog>
</dogs>
Run Code Online (Sandbox Code Playgroud)

此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>
Run Code Online (Sandbox Code Playgroud)

这是孩子一:

<?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>
Run Code Online (Sandbox Code Playgroud)

孩子包括常见的孩子(称为transform.xslt).

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

First template
        Other template
Run Code Online (Sandbox Code Playgroud)

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

First template


        Doggy


        Unknown
Run Code Online (Sandbox Code Playgroud)

常见的模板应用模式"othertemplate".此模式仅在子xslt中包含.

我想要的是,如果没有模板"othertemplate",那么就不应输出任何内容.

我不希望为所有不必使用此模板模式的xslt文件包含模式为"othertemplate"的模板和空体...

我该怎么办?

谢谢

jas*_*sso 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()"/>
Run Code Online (Sandbox Code Playgroud)

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

每种模式都有一个内置的模板规则.这些模板类似于元素和root的默认模板,除了它们以相同模式继续处理.

<xsl:template match="*|/" mode="foobar">
  <xsl:apply-templates mode="foobar"/>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)

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

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

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

<xsl:template match="foobar">
  <!-- This is an infinite loop -->
  <xsl:apply-templates select="."/>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)

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

  • +1用于xslt对内置模板及其应用的详细说明. (2认同)

Dim*_*hev 6

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

要禁止这一点,您需要使用空模板覆盖所需模式的文本节点(也可能是元素)的内置模板:

<xsl:template match="text()" mode="othertemplate"/>
Run Code Online (Sandbox Code Playgroud)

在导入的样式表中包含上述内容.