XSLT variable reference using dynamic name

I am stuck with a little problem.

XSL file:

<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fn="http://www.w3.org/2005/xpath-functions"> <xsl:template match="/"> <xsl:variable name="unumericValue" select="10" /> <xsl:variable name="uanotherValue" select="8" /> <xsl:for-each select="/root/try"> <xsl:value-of select="var" /> <xsl:variable name="min"><xsl:value-of select="@minimum" /></xsl:variable> <xsl:value-of select="@type" /> <xsl:variable name="referenceName"><xsl:value-of select='concat("u",var)' /></xsl:variable> <xsl:value-of select="$referenceName" /> <xsl:if test='$referenceName > $min'> <p>Do something.</p> </xsl:if> </xsl:for-each> </xsl:template> </xsl:stylesheet> 

XML file:

 <?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="q1.xsl"?> <root> <try type="compare" minimum="9"> <var>numericValue</var> <something>...</something> </try> <try type="compare" minimum="10"> <var>anotherValue</var> <something>...</something> </try> </root> 

As you can see, the XML file contains two var-Elements that must match the variables in the XSLT file. However, I do not know which syntax is correct. $ referenceName is just the name of the variable I want to use. But I do not know how to refer to the name of an existing variable.

+6
source share
3 answers

$referenceName not a reference to a variable named "unumericValue" or otherwise. This is just the string value of "unumericValue", etc. So there will never be more than $min . However, with a little extra work, there is a trick to find a variable by its name:

 <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:variable name="numericValue" select="10" /> <xsl:variable name="anotherValue" select="8" /> <xsl:variable name="vars" select="document('')/*/xsl:variable" /> <xsl:template match="/"> <xsl:variable name="referenceName" select="'numericValue'" /> <xsl:variable name="referenceValue" select="$vars[@name = $referenceName]/@select" /> Reference value: <xsl:value-of select="$referenceValue" /> </xsl:template> </xsl:stylesheet> 

One big limitation to note here is that this will only work for variables that are a constant numeric value.

Here you can simulate variables with constant string values:

 <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:v="variables-node" > <v:variables> <v:variable n="numericValue" value="10" /> <v:variable n="nonNumericValue" value="Hello World" /> </v:variables> <xsl:variable name="vars" select="document('')//v:variables/v:variable" /> <xsl:template match="/"> <xsl:variable name="referenceName" select="'nonNumericValue'" /> <xsl:variable name="referenceValue" select="$vars[@n = $referenceName]/@value" /> <xsl:value-of select="concat('The variable with the name ', $referenceName, ' has the value ', $referenceValue)"/> </xsl:template> </xsl:stylesheet> 

And finally, a way to model variables with calculated values:

 <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common" > <xsl:variable name="varsRaw"> <var n="computedValue" value="{concat('2 + 4 is ', 2 + 4)}" /> <var n="computedNumber" value="{22 div 7}" /> </xsl:variable> <xsl:variable name="vars" select="exslt:node-set($varsRaw)/var" /> <xsl:template match="/"> <xsl:variable name="referenceName" select="'computedValue'" /> <xsl:variable name="referenceValue" select="$vars[@n = $referenceName]/@value" /> <xsl:value-of select="concat('The variable with the name ', $referenceName, ' has the value ', $referenceValue)"/> <xsl:value-of select="' '"/> <xsl:variable name="referenceName2" select="'computedNumber'" /> <xsl:variable name="referenceValue2" select="$vars[@n = $referenceName2]/@value" /> <xsl:value-of select="concat('The variable with the name ', $referenceName2, ' has the value ', $referenceValue2)"/> </xsl:template> </xsl:stylesheet> 

The latter approach is probably the most orthodox one, but it requires an XSLT-dependent (at least in XSLT 1.0) node-set() function.

+11
source

By the way, do not do this:

 <xsl:variable name="min"><xsl:value-of select="@minimum" /></xsl:variable> 

when you can do this:

 <xsl:variable name="min" select="@minimum" /> 

It is not only detailed, but also inefficient - there is no need to copy data and build a new tree, which is a very expensive operation, when all you need is a link to an existing node.

+5
source

As with most programming languages, XSLT variable names are not available at run time. The variable may not even exist at run time - the optimizer is allowed to play all kinds of tricks, for example, insert all references to the variable at the point where the variable is used.

The best approach is to have a variable with a standard name and provide it with XML content. XML element and attribute names are available at run time, unlike variable names.

+1
source

All Articles