如何测试路径在变量中给出的节点的存在

时间:2014-09-20 13:12:31

标签: xslt xpath

我是XSLT的新手,并且还没有使用它的语法。

我有一个变量(name =" pageName"),它包含xml源树中页面元素的xpath。例如:

  

/数据/全树/页[@Handle ='恩'] /页[@Handle ='学习'] /页[@Handle ='教程& #39]

在html页面中显示此页面的链接之前,我想确保页面元素存在,因此我编写了以下 if test:

<xsl:if test="$pageName" >
    <a>
        <xsl:attribute name="href" >
            <xsl:value-of select='$theLink' />
        </xsl:attribute>
        Click here
    </a>
</xsl:if>

但它没有按预期工作,因为即使xpath指向的页面元素不存在于树中,测试结果也始终为true。 另一方面,当我将变量的内容直接写入测试变量时,如下所示:

 <xsl:if test="/data/full-tree/page[@handle='en']/page[@handle='learn']/page[@handle='tutorials']
    <a>
        <xsl:attribute name="href" >
            <xsl:value-of select='$theLink' />
        </xsl:attribute>
        Click here
    </a>
</xsl:if>   

它似乎工作并在页面元素存在时显示链接,但在页面元素不存在时显示。

我的问题是如何正确使用我的变量?

修改

我会尝试让我的背景更加详细

xml源代码树(代表网站的结构就像这样

<data>
<full-tree>
    <page handle="root" id="12">
        <name>Root Page</name>
        <types>
            <type>index</type>
        </types>
    </page>

    <page handle="en" id="1">
        <name>EN Root</name>
        <types>
            <type>en</type>
        </types>
        <page handle="home" id="3">
            <name>Home</name>
            <types>
                <type>en</type>
            </types>
        </page>
        <page handle="about" id="7">
            <name>About</name>
            <types>
                <type>en</type>
            </types>
            <page handle="about-zoraldia" id="8">
                <name>About zoraldia</name>
                <types>
                    <type>en</type>
                </types>
            </page>
        </page>
        <page handle="learn" id="21">
            <name>Learn</name>
            <types>
                <type>en</type>
            </types>
            <page handle="tutorials" id="22">
                <name>Tutorials</name>
                <types>
                    <type>en</type>
                </types>
                <page handle="symphony" id="24">
                    <name>Symphony</name>
                    <types>
                        <type>en</type>
                    </types>
                    <page handle="create-site" id="23">
                        <name>Create a bilingual Web Site with the Symphony CMS</name>
                        <types>
                            <type>en</type>
                            <type>web-site</type>
                        </types>
                    </page>
                    <page handle="symphony-menu-page" id="48">
                        <name>Add level 3 and 4 Menu Pages</name>
                        <types>
                            <type>en</type>
                            <type>symphony</type>
                        </types>
                    </page>
                </page>
            </page>
        </page>
        <page handle="think" id="49">
            <name>Think</name>
            <types>
                <type>en</type>
            </types>
            <page handle="free-software" id="50">
                <name>Free Software</name>
                <types>
                    <type>en</type>
                </types>
                <page handle="miscellaneous" id="51">
                    <name>Miscellaneous Articles</name>
                    <types>
                        <type>en</type>
                    </types>
                    <page handle="philo" id="52">
                        <name>Philosophy and Values of Free Software</name>
                        <types>
                            <type>en</type>
                        </types>
                    </page>
                </page>
            </page>
        </page>
    </page>
    <page handle="maintenance" id="9">
        <name>Maintenance notification</name>
        <types>
            <type>maintenance</type>
        </types>
    </page>
</full-tree>
<data>

这表示英文页面,但法语中也有待处理的结构。 我想要做的是当访问者在法语页面上时,仅在页面被翻译时显示EN链接。

因此我使用法语路径(例如/ fr / learn / tutorials,只需将fr与/ en / learn / tutorials交换为$ enLink变量。

我的目标是显示只有在页面存在时才能正常运行的链接。

我使用一个定义为

的变量
    <xsl:variable name="pending">
             <xsl:call-template name="build-xpath">
               <xsl:with-param name="output-string" select="'/data/full-tree'" />
               <xsl:with-param name="input-string" select="substring-after($enLink,'/')" />
           </xsl:call-template>
     </xsl:variable>

build-xpath算法如下:

<xsl:template name="build-xpath" >
    <xsl:param name="output-string" />
    <xsl:param name="input-string" />

     <xsl:choose>
         <xsl:when test="contains($input-string, '/')" >

            <xsl:variable name="new-output">
               <xsl:value-of select="$output-string" />/page[@handle='<xsl:value-of select="substring-before($input-string,'/')"/>']
            </xsl:variable>

            <xsl:variable name="new-input" >
                <xsl:value-of select="substring-after($input-string,'/')" />
            </xsl:variable >

            <xsl:call-template name="build-xpath" >
               <xsl:with-param name="output-string"  select="$new-output" />
               <xsl:with-param name="input-string" select="$new-input" />
            </xsl:call-template>


         </xsl:when>


         <xsl:otherwise><xsl:value-of select="$output-string"/>/page[@handle='<xsl:value-of select="$input-string"/>']
         </xsl:otherwise>


     </xsl:choose>


</xsl:template>

此算法返回挂起的变量(我最初称为 pageName 的变量)

显示
<xsl:value-of select="$pending" />

我看到了字符串

  

/数据/全树/页[@Handle =&#39;恩&#39;] /页[@Handle =&#39;学习&#39;] /页[@Handle =&#39;教程& #39]

这是我对算法的期望。

让我遇到麻烦的是,当我将此字符串放入另一个变量时,请说 anotherVar

<xsl:value-of select="$anotherVariable" 

不显示字符串,但显示节点的内容,在这种情况下:

  

教程en

这看起来很正常,但为什么在$ pending的情况下显示字符串本身?

1 个答案:

答案 0 :(得分:2)

由于您的变量是字符串,因此在布尔测试中对其进行评估将始终返回true,因为只有空字符串的计算结果为false。

为了将变量评估为节点,您需要首先将字符串转换为Xpath表达式。这可以在XSLT 3.0中本机完成。在以前的版本中,您需要使用扩展功能,例如EXSLT dyn:evaluate()函数 - 如果您的处理器支持它。

可能有一种更简单的方法来处理这个问题,但我们没有看到足够的整个画面以确定(我在输入中没有看到任何法语元素)。我怀疑,例如,通过使用某个公共ID来测试是否存在相应的节点会更加直接。