复制 XSLT 变量

7
我正在处理一个Umbraco XSL样式表,目前遇到了困难。
基本上,我有一个参数需要进行测试,并且如果存在,则使用它的值,否则使用默认参数$currentPage
以下是我的参数:
<xsl:param name="source" select="/macro/sourceId" />
<xsl:param name="currentPage" />

这是变量。
<xsl:variable name="current">
    <xsl:choose>
        <xsl:when test="$source &gt; 0">
            <xsl:copy-of select="umbraco.library:GetXmlNodeById($source)" />
        </xsl:when>
        <xsl:otherwise>
            <xsl:copy-of select="$currentPage" />
        </xsl:otherwise>
    </xsl:choose>
</xsl:variable>

这就是我使用它的地方。
<xsl:for-each select="msxml:node-set($source)/ancestor-or-self::* [@isDoc and @level=$level]/* [@isDoc and string(umbracoNaviHide) != '1']">
... code here ...
</xsl:for-each>

简而言之:
这个有效。
<xsl:variable name="source" select="$currentPage" />

这个没有。
<xsl:variable name="source">
  <xsl:copy-of select="$currentPage" /> <!-- Have tried using <xsl:value-of /> as well -->
</xsl:variable>

那么,如果不使用select=""属性,如何复制一个变量?

更新:我尝试使用另一种方法(见下文),但是我收到了一个“变量超出范围”的异常。

<xsl:choose>
    <xsl:when test="$source &gt; 0">
        <xsl:variable name="current" select="umbraco.library:GetXmlNodeById($source)" />
    </xsl:when>
    <xsl:otherwise>
        <xsl:variable name="current" select="$currentPage" />
    </xsl:otherwise>
</xsl:choose>

XSLT1还是2?$currentPage定义在哪里?它的类型是什么? - Jim Garrison
嗨@Jim,这是XSLT 1.0(Umbraco),$currentPage是一个内置参数,它包含当前页面及其子级的节点集。 - Marko
我所尝试做的,@Jim,就是根据一个测试条件,让$source有一个不同的值。 - Marko
你能解释一下你看到的行为与你期望的不符吗?仅仅说“这不起作用”是不够的。 - Jim Garrison
1
@Jim,你不理解问题的哪一部分?我有一个名为$currentPage的参数,其中包含一个节点集。当我尝试使用<xsl:variable name="source" select="$currentPage" />复制参数时,我得到了预期的输出(节点集)。当我尝试在<xsl:parameter></xsl:parameter>中使用<xsl:copy-of /><xsl:value-of />复制参数时,我得到的是文本而不是预期的XML输出。 - Marko
显示剩余2条评论
2个回答

6

通常,此表达式根据给定条件为true()还是false()选择两个节点集之一:

$ns1[$cond] | $ns2[not($cond)]

在你的情况下,这意味着:
    umbraco.library:GetXmlNodeById($source) 
|
    $currentPage[not(umbraco.library:GetXmlNodeById($source))]

<xsl:variable>的完整定义如下:

<xsl:variable name="vCurrent" select=
"        umbraco.library:GetXmlNodeById($source) 
    |
        $currentPage[not(umbraco.library:GetXmlNodeById($source))]
"/>

这可以以更紧凑的方式书写:

<xsl:variable name="vRealSource" select="umbraco.library:GetXmlNodeById($source)"/>

<xsl:variable name="vCurrent" select=
    "$vRealSource| $currentPage[not($vRealSource)]"/>

嗯,我无法让它工作,它没有输出任何内容。在这种情况下,not()到底是做什么的?它是检查空字符串还是其他什么? - Marko
我将not($vRealSource)更改为not($source),现在它可以工作了。非常感谢,感激不尽。 - Marko

2

当您在XSLT 1.0中声明一个没有@select但带有一些内容模板的变量时,该变量的类型将为结果树片段。该变量保存此树片段的根节点。

因此,使用以下代码:

<xsl:variable name="source"> 
  <xsl:copy-of select="$currentPage" />
</xsl:variable> 

您正在声明$source作为包含$currentPage节点集中的节点(自身和后代)的副本的RTF的根。

不能在RTF中使用/步骤运算符。这就是为什么要使用node-set扩展函数的原因。

但是,当您说:

node-set($source)/ancestor-or-self::*

这将被评估为一个空节点集,因为根节点没有祖先且不是元素。

编辑:如果您有两个节点集,并且您想根据某些条件声明一个变量,其内容取决于其中一个节点集的内容,则可以使用:

<xsl:variable name="current" 
              select="umbraco.library:GetXmlNodeById($source)[$source > 0]
                      |$currentPage[0 >= $source]" /> 

谢谢@Alejandro,你会建议我在这种情况下该怎么做吗?我基本上试图根据一个测试来使用不同的来源。$currentPage单独使用和在使用@select时都很好用。 - Marko
@Marko Ivanovski:请看我的编辑,这是一个解决方案。请注意,条件应该是互斥的,并且要注意上下文(由于变量引用,这两个条件是“自由”的)。 - user357812

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接