【问题标题】:How to test for existence of a node whose path is given in a variable如何测试是否存在路径在变量中给出的节点
【发布时间】:2014-11-14 22:45:34
【问题描述】:

我是 XSLT 的新手,还不熟悉它的语法。

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

/data/full-tree/page[@handle='en']/page[@handle='learn']/page[@handle='tutorials']

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

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

但它不能按预期工作,因为即使 xpath 指向的页面元素在树中不存在,测试结果也始终为真。 另一方面,当我像这样将变量的内容直接写入测试变量时:

 <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 交换,从而将 /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>

这个算法返回一个 pending 变量(我一开始称为 pageName 的那个)

显示为

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

我看到了字符串

/data/full-tree/page[@handle='en']/page[@handle='learn']/page[@handle='tutorials']

这就是我对算法的期望。

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

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

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

教程zh

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

【问题讨论】:

    标签: xslt xpath


    【解决方案1】:

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

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

    可能有一种更简单的方法来处理这个问题,但为了确定,我们看不到整个图片(我在您的输入中没有看到任何法国元素)。例如,我怀疑通过使用一些通用 ID 来测试相应节点的存在会更加直接。

    【讨论】:

    • 您可能是对的,我将尝试了解如何使用它。尽管如此,我不明白为什么将字符串直接放入一个变量并在测试中使用这个变量,而不是我用我的算法构建的一个变量。至于法国元素,它们是存在的,我只是为了节省空间而删除了它们。
    • "我不明白为什么将字符串直接放入变量并在测试中使用此变量," 这是因为您没有放入 字符串 变成了变量,而是一个表达式。如果您将变量定义为:&lt;xsl:variable name="pending" select="'yourpath'"/&gt;(注意引号!)那么您将拥有与使用命名模板构建路径时所做的相同的操作。
    • 好的,我明白了。这是我从一开始就错过的东西。
    猜你喜欢
    • 2010-10-03
    • 1970-01-01
    • 2021-07-03
    • 1970-01-01
    • 1970-01-01
    • 2012-02-09
    • 2011-08-05
    • 2015-04-05
    • 2016-04-29
    相关资源
    最近更新 更多