谓词中的XSLT generate-id()不起作用

时间:2017-08-16 14:01:01

标签: xml xslt

我在谓词中使用generate-id()函数与之前生成的id进行比较。但这不起作用,我无法弄清楚为什么。

我已经创建了一个带有输入和预期输出的示例XSLT。是的我知道 - 这段代码似乎很奇怪而且没有意义,只是要找出,为什么generate-id()在这里不起作用。

问题行如下:

<xsl:value-of select="a[generate-id(current())=$a_id]/text()"/>

这不起作用。这里是完整的XML输入,XSLT和预期输出。

XML输入:

<root>
    <test>
        <a>1</a>
        <a>2</a>
        <a>3</a>
    </test>
</root>

预期产出:

<root>
    <test>
        <a>1</a>
    </test>
    <test>
        <a>2</a>
    </test>
    <test>
        <a>3</a>
    </test>
</root>

结果输出(使用id搜索找不到值):

<root>
    <test>
        <a/>
    </test>
    <test>
        <a/>
    </test>
    <test>
        <a/>
    </test>
</root>

这是XSLT。问题出在最后一个模板中:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
    <xsl:output indent="yes"></xsl:output>    

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

    <xsl:template match="test">
        <xsl:for-each select="a">
            <xsl:apply-templates select=".." mode="output">
                <xsl:with-param name="a_id" select="generate-id()"/>
            </xsl:apply-templates>
        </xsl:for-each>
    </xsl:template>

    <xsl:template match="test" mode="output">
        <xsl:param name="a_id"/>
        <xsl:copy>
            <xsl:element name="a">
                <!-- Here the passed a_id cannot be found -->
                <xsl:value-of select="a[generate-id(current())=$a_id]/text()"/>
            </xsl:element>            
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

2 个答案:

答案 0 :(得分:1)

你的问题的答案是你需要这样做......

<xsl:value-of select="a[generate-id(.)=$a_id]/text()"/>

甚至这个......

<xsl:value-of select="a[generate-id()=$a_id]/text()"/>

current()指的是匹配的当前节点,即test节点。 .引用当前上下文(a节点)。有关详细信息,请参阅Current node vs. Context node in XSLT/XPath?

另一个答案是你可能有过于复杂的事情。你可以重新编写你的XSLT ..

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
    <xsl:output indent="yes"></xsl:output>    

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

    <xsl:template match="test">
        <xsl:for-each select="a">
            <test>
              <xsl:apply-templates select="." />
            </test>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

答案 1 :(得分:1)

template match="test"内,current()函数会选择匹配test,因此我认为您只是想要

a[generate-id(.)=$a_id]

确保您将a元素的ID与test元素的ID与a元素进行比较。另请注意,在XSLT 2.0中有一个is运算符,因此您不需要传递ID并比较它们,您可以直接传递元素并输出它,或者,如果您需要比较一些基于身份的节点,使用is运算符。