Copying an XSLT variable
Question
I'm working on an Umbraco XSL Stylesheet and I am pretty stuck.
Basically, I have a parameter that I test and use it's value if it's present, otherwise I use the default parameter $currentPage
.
Here are the parameters
<xsl:param name="source" select="/macro/sourceId" />
<xsl:param name="currentPage" />
Here's the variable
<xsl:variable name="current">
<xsl:choose>
<xsl:when test="$source > 0">
<xsl:copy-of select="umbraco.library:GetXmlNodeById($source)" />
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="$currentPage" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
And here's where I use it
<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>
In a nutshell
This works
<xsl:variable name="source" select="$currentPage" />
This doesn't
<xsl:variable name="source">
<xsl:copy-of select="$currentPage" /> <!-- Have tried using <xsl:value-of /> as well -->
</xsl:variable>
So how do you copy a variable without using the select=""
attribute.
UPDATE: I've tried using another approach (see below) but I get a variable out of scope exception.
<xsl:choose>
<xsl:when test="$source > 0">
<xsl:variable name="current" select="umbraco.library:GetXmlNodeById($source)" />
</xsl:when>
<xsl:otherwise>
<xsl:variable name="current" select="$currentPage" />
</xsl:otherwise>
</xsl:choose>
Solution
Generally, this expression selects one of two nodesets, based on whether a given condition is true()
or false()
:
$ns1[$cond] | $ns2[not($cond)]
In your case this translates to:
umbraco.library:GetXmlNodeById($source)
|
$currentPage[not(umbraco.library:GetXmlNodeById($source))]
The complete <xsl:variable>
definition is:
<xsl:variable name="vCurrent" select=
" umbraco.library:GetXmlNodeById($source)
|
$currentPage[not(umbraco.library:GetXmlNodeById($source))]
"/>
This can be written in a more compact way:
<xsl:variable name="vRealSource" select="umbraco.library:GetXmlNodeById($source)"/>
<xsl:variable name="vCurrent" select=
"$vRealSource| $currentPage[not($vRealSource)]"/>
OTHER TIPS
Whenever you declare a variable in XSLT 1.0 without @select, but with some content template, the variable type will be of Result Tree Fragment. The variable holds the root node of this tree fragment.
So, with this:
<xsl:variable name="source">
<xsl:copy-of select="$currentPage" />
</xsl:variable>
You are declaring $source
as the root of a RTF containing the copy of the nodes (self and descendants) in $currentPage
node set.
You can't use /
step operator with RTF. That's why you are ussing node-set
extension function.
But, when you say:
node-set($source)/ancestor-or-self::*
This will be evaluate to an empty node set, because a root node hasn't ancestors an it's not an element.
EDIT: If you have two node sets, and you want to declare a variable with the content of one of the two node sets depending on some condition, you could use:
<xsl:variable name="current"
select="umbraco.library:GetXmlNodeById($source)[$source > 0]
|$currentPage[0 >= $source]" />