何时应用了xsl:template的match-attribute? (以及如何覆盖)

时间:2010-08-18 13:23:10

标签: xslt

由于我已经理解了模板标记的匹配属性,因此它定义了将包含在模板中的xml树的哪个部分。

然而,似乎是一些例外,我有一个工作的代码和平,精简这个:

<xsl:template match="/root/content">
    <xsl:for-each select="/root/meta/errors/error">
        <p>
            <strong>Error:</strong> <xsl:value-of select="message" /> (<xsl:value-of select="data/param" />)<br />
            <xsl:for-each select="data/option">
                <xsl:value-of select="." /><br />
            </xsl:for-each>
        </p>
        <br /><br />
    </xsl:for-each>
</xsl:template>

但是当我尝试添加这样的条件时:

<xsl:template match="/root/content">
    <xsl:if test="not(/root/meta/error/errors/data/param)"-->
        <xsl:for-each select="/root/meta/errors/error">
            <p>
                <strong>Error:</strong> <xsl:value-of select="message" /> (<xsl:value-of select="data/param" />)<br />
                <xsl:for-each select="data/option">
                    <xsl:value-of select="." /><br />
                </xsl:for-each>
            </p>
            <br /><br />
        </xsl:for-each>
        <xsl:call-template name="trip_form">
            <xsl:with-param name="type" select="'driver'" />
                <xsl:with-param name="size" select="'savetrip'" />
            </xsl:call-template>
    </xsl:if>
</xsl:template>

它不再起作用,为什么,以及如何让它再次起作用?

1 个答案:

答案 0 :(得分:3)

当你提出要求时会应用属性匹配(你正在使用复杂且不需要的for-each,导致根本没有属性匹配),否则它们会被忽略。这就是复制习惯用法与特定属性apply-templates一起使用的原因:

<xsl:template match="node() | @*">
   <xsl:copy>
      <xsl:apply-templates select="* | @*" />
   </xsl:copy>
</xsl:template>

当涉及应用它们的 order 时,顺序是文档顺序,这意味着:在应用元素之后,将应用其属性(以未确定的顺序),然​​后应用元素的子元素。属性永远不会有子节点,它们的父节点是包含元素。

  

“它定义了将包含在模板中的xml树的哪个部分。”

没有。当处理器遇到与规范匹配的输入时,或者使用xsl:apply-templates专门应用此输入时,将调用此方法。您的代码不应使用xsl:for-each,这很少需要。相反,请使用xsl:apply-templates。这也可以让您在需要时匹配属性。

通常,您(不需要)在apply-templates的match-attribute中指定父级。你肯定不会每次都写下模板内部的整个路径,这会对你的样式表的可用性造成严重破坏......尝试这样的东西,看看网上的一些XSL教程(w3schools提供了一些基础知识)信息和Tennison的书非常值得了解这种函数式编程的变体:

<xsl:template match="/">
   <xsl:apply-templates select="/root/content" />
</xsl:template>

<xsl:template match="content">
   <xsl:apply-templates select="errors/error" />
</xsl:template>

<xsl:template match="error">
    <p>
        <strong>Error:</strong> 
        <xsl:value-of select="message" /> 
        (<xsl:value-of select="data/param" />)
        <br />
        <xsl:apply-templates select="data/option" />
    </p>
    <br /><br />
</xsl:template>

<xsl:template match="option">
   <xsl:value-of select="." /><br />
</xsl:template>
  

“它不再起作用,为什么,以及如何让它再次运作?”

因为你的if语句可能总是正确的(或总是假的)。原因:如果文档中的任何地方XPath是正确的,它将永远是错误的,如果它永远不正确,它将永远是真的。将xsl:if与在根中开始的XPath一起使用,对于转换的实时,总是产生相同的结果。不知道你在追求什么,所以我不能在这里帮助你。通常情况下,我们倾向于使用匹配的模板而不是xsl:if(再次,是的,我知道它很无聊;)。

注意:您在问题中询问某些属性,我尝试在开头段落(在此编辑之前)回答。但是,代码中没有关于属性的内容,所以我不知道如何真正帮助你。

注意事项:LarsH表示您可能想询问match内的xsl:template - 属性。如果是这样,答案就在上面的任何地方的文本中,我在那里谈论应用模板和排序。简而言之:输入文档是逐节点处理的,可能由xsl:apply-templates指导,它试图为当前所在的每个节点找到匹配的模板。这就是它的全部内容。