代码之家  ›  专栏  ›  技术社区  ›  Jagger

无法在XSLT 2.0中的match XPath表达式中使用模板参数?

  •  3
  • Jagger  · 技术社区  · 8 年前

    this 所以问题是,应该可以在XPath表达式中为 match . 然而,如果 xsl:param xsl:template 将在同一模板中使用。

    <?xml version="1.0" encoding="UTF-8"?>
    <myRoot>
        <myNode myAttribute="3">
            <myChildAttribute myChildAttribute="a" />
        </myNode>
        <myNode myAttribute="2">
            <myChildAttribute myChildAttribute="b" />
        </myNode>
        <myNode myAttribute="1" />
    </myRoot>
    

    我的XSL文件就是这样。

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="2.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="text" encoding="UTF-8"/>
    
        <xsl:template match="myRoot">
            <xsl:apply-templates select="myNode">
                <xsl:sort select="@myAttribute" />
                <xsl:with-param name="myParam" select="max(myNode/@myAttribute)" />
            </xsl:apply-templates>
        </xsl:template>
    
        <xsl:template match="myNode[node() and @myAttribute = $myParam]">
            <xsl:param name="myParam" />
                <xsl:for-each select="myChildAttribute">
    INSERT INTO a(b) VALUES ('<xsl:value-of select="@myChildAttribute" />');
                </xsl:for-each>
        </xsl:template>
    
    </xsl:stylesheet>
    

    不幸的是,当使用SAXON 9HE运行时,它以以下错误结束

    XPST0008: Variable myParam has not been declared (or its declaration is not in scope)
    

    在的match XPath表达式中不能使用模板的参数吗 相同的 样板

    2 回复  |  直到 8 年前
        1
  •  3
  •   Dimitre Novatchev    8 年前

    是否无法在中使用模板的参数 匹配同一模板的XPath表达式!?

    否,当选择要执行的模板时,模板的匹配表达式中的任何变量/参数都必须在范围内(已定义/可见)。

    因为模板是XSLT指令(在全局级别定义),所以范围内(它们可以看到)的唯一变量/参数是全局级别的变量/参数。

    只有在选择执行模板之后,才将模板的参数传递给它,而不是在此之前。这意味着在执行模板选择过程时,该参数的值不存在。

    select 对应的属性 xsl:apply-templates 指令,其中可以计算此表达式--而不是在 match 属性,其中无法计算此表达式。

    为了明确这一点,以下代码更正了所提供代码中的问题 :

    <xsl:stylesheet version="2.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
            <xsl:output method="text" encoding="UTF-8"/>
    
            <xsl:template match="myRoot">
                <xsl:apply-templates select="myNode[@myAttribute = max(../myNode/@myAttribute)]">
                    <xsl:sort select="@myAttribute" />
                </xsl:apply-templates>
            </xsl:template>
    
        <xsl:template match="myNode[node()]">
                 <xsl:for-each select="myChildAttribute">
    INSERT INTO a(b) VALUES ('<xsl:value-of select="@myChildAttribute" />');
                </xsl:for-each>
        </xsl:template>
    
    </xsl:stylesheet>
    

    :

    <myRoot>
        <myNode myAttribute="3">
            <myChildAttribute myChildAttribute="a" />
        </myNode>
        <myNode myAttribute="2">
            <myChildAttribute myChildAttribute="b" />
        </myNode>
        <myNode myAttribute="1" />
    </myRoot>
    

    (我不能说“正确的输出”,因为没有定义任何要求,因此无法对其进行验证。我对此代码持保留意见:例如,使用 <xsl:sort> 的子女 xsl:应用模板 没有意义,因为它将对相等(max())值进行排序,并且对相等值序列进行排序会产生相同的序列):

    INSERT INTO a(b) VALUES ('a');
    
        2
  •  2
  •   fhossfel    8 年前

    我认为这行不通。参数在您定义的模板内有效。但是,匹配表达式实际上不是模板的一部分。当myParam尚未定义时,必须从外部对其进行评估。

    您必须将max(myNode/@myAttribute)的过滤移到应用模板调用的选择表达式。