Reputation: 27516
Deep inside a stylesheet, I have some logic that looks sort of like this:
<xsl:variable name="v1">
<!-- define structure within v1 -->
</variable>
<xsl:variable name="v2">
<!-- define structure within v2 -->
</variable>
<xsl:variable name="valuesMap" select="exsl:node-set($v1)"/>
<xsl:variable name="valuesMap_2" select="exsl:node-set($v2)"/>
...
<xsl:variable name="tmp">
<xsl:choose>
<xsl:when test="$isSomeCondition">
<xsl:copy-of select="$valuesMap"/>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="$valuesMap_2"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="valueSet" select="exsl:node-set($tmp)"/>
<xsl:choose>
<xsl:when test="not($valueSet/Child[@someAttribute=$someOtherVariable])">
...
</xsl:when>
...
The variables $valuesMap
and $valuesMap_2
are variables that contain node sets. They are defined elsewhere and are referenced several places in this transformation.
What I am trying to do is check a condition ($isSomeCondition
) and then set a local variable, $valueSet
, to refer to either $valuesMap
or $valuesMap_2
. I'm doing this because there are several places in this template where I need to choose between $valuesMap
or $valuesMap_2
and I'd rather just make the decision once and use a local variable to keep track of it.
The code above works, but I'm concerned about using copy-of
: I fear it will completely duplicate the contents of $valuesMap
or $valuesMap_2
, and that could be a problem because these variables could contain some rather large structures and this specific template will be used numerous times per transformation.
I've already tried using value-of
but that seems to capture the text content of the variables, not the XML structure.
Is there any way to reference the correct structure without having to copy it?
Upvotes: 2
Views: 44
Reputation: 27516
I found an alternate solution using the "evaluate" function in then "dynamic" package of EXSLT:
<xsl:variable name="tmpName">
<xsl:choose>
<xsl:when test="$isSomeCondition">
<xsl:text>$valuesMap</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>$valuesMap_2</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="valueSet" select="dyn:evaluate($tmpName)"/>
<xsl:choose>
<xsl:when test="not($valueSet/Child[@someAttribute=$someOtherVariable])">
...
</xsl:when>
...
On the other hand, this uses an eval
function... I'd guess that Ian's still performs better than this, ...and I'd guess that this solution probably performs better than my original problem which used copy-of
.
Upvotes: 0
Reputation: 122394
Combine the two variables into one, e.g.
<xsl:variable name="vMapRTF">
<v1>
<!-- define structure within v1 -->
</v1>
<v2>
<!-- define structure within v2 -->
</v2>
</xsl:variable>
<xsl:variable name="vMap" select="exsl:node-set($vMapRTF)" />
<xsl:variable name="valueSet" select="$vMap/*[2 - $isSomeCondition]" />
Here I'm taking advantage of the fact that a boolean expression in a numeric context is treated as 0
if it's false and 1
if it's true, so if $isSomeCondition
is true it'll pick $vMap/*[1]
(the v1
element) and if it's false it'll pick $vMap/*[2]
.
If you still need the separate $valuesMap
and $valuesMap_2
variables for use elsewhere in the transformation then just declare them as e.g.
<xsl:variable name="valuesMap" select="$vMap/v1" />
Upvotes: 3