XSLT:将变量传递给xpath

时间:2014-07-25 19:03:33

标签: xml xslt

在XSLT中,我将模板定义为:

<xsl:template name="AA">
        <xsl:param name="pre_path" />
        <xsl:value-of select="concat($pre_path, 'A/B')" />
</xsl:template>

呼叫模板

<xsl:call-template name="AA">
    <xsl:with-param name="pre_path" select="'C/'"/>
</xsl:call-template>

的xml:

<C>
 <A>
  <B>Hello world</B>
 </A>
</C>

为什么结果输出是C / A / B,而不是“Hello world”?

我期待:

<xsl:value-of select="C/A/B" />

获取“Hello world”

提前致谢,

1 个答案:

答案 0 :(得分:0)

以下是有关如何实现选择匹配元素值的动态XPath的几个选项。

XSLT 1.0 样式表,它使用递归模板生成动态XPath,为文档中的每个元素调用,并与谓词过滤器内部的连接路径进行比较。

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="/">      
        <xsl:call-template name="AA">
            <xsl:with-param name="pre_path" select="'C/'"/>
        </xsl:call-template>
    </xsl:template>

    <xsl:template name="AA">
        <xsl:param name="pre_path"/>
        <xsl:for-each select="//*">
            <xsl:variable name="dynamic-xpath">
                <xsl:call-template name="make-xpath">
                    <xsl:with-param name="context-item" select="."/>
                </xsl:call-template>
            </xsl:variable>

            <xsl:value-of select="self::*[concat($pre_path,'A/B') = 
                                  $dynamic-xpath]"/>
        </xsl:for-each>    
    </xsl:template>

    <xsl:template name="make-xpath">
        <xsl:param name="context-item"/>
        <xsl:param name="path"/>

        <xsl:variable name="new-path">
            <xsl:value-of select="local-name($context-item)"/>
            <xsl:if test="normalize-space($path)">
                <xsl:value-of select="concat('/',$path)"/>
            </xsl:if>
        </xsl:variable>

        <xsl:choose>
            <xsl:when test="$context-item/parent::*">
                <xsl:call-template name="make-xpath">
                    <xsl:with-param name="context-item" 
                                    select="$context-item/parent::*"/>
                    <xsl:with-param name="path" select="$new-path"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$new-path"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

</xsl:stylesheet>

一个 XSLT 2.0 样式表,它构造一个动态表达式,并将其与谓词过滤器内的每个元素的串联$pre_path和静态'A/B'值进行比较。该文件。

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="/">
        <xsl:call-template name="AA">
            <xsl:with-param name="pre_path" select="'C/'"/>
        </xsl:call-template>
    </xsl:template>

    <xsl:template name="AA">
        <xsl:param name="pre_path"/>
        <xsl:value-of select="//*[concat($pre_path,'A/B') = 
                       string-join(ancestor-or-self::*/local-name(), '/')]"/>
    </xsl:template>

</xsl:stylesheet>

利用xsl:evaluate利用动态XPath选择项目的 XSLT 3.0 解决方案:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="3.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="/">
        <xsl:call-template name="AA">
            <xsl:with-param name="pre_path" select="'C/'"/>
        </xsl:call-template>
    </xsl:template>

    <xsl:template name="AA">
        <xsl:param name="pre_path"/>
        <xsl:variable name="items" as="node()*">
            <xsl:evaluate xpath="concat($pre_path,'A/B')"/>
        </xsl:variable>
        <xsl:value-of select="$items"/>
    </xsl:template>

</xsl:stylesheet>