Reputation: 7876
Is it possible using XSL to access a variable (or a parameter) whose name is stored in another variable (or parameter)? If no, why?
I am new to xsl, coming from other languages, where this functionality is accessible, like bash, ant. Maybe I was wrong even looking for an answer to this question. But since I didn't find it on SO, I think there should be one.
Two examples. I have parameters p1
, p2
, p3
. Then I have a parameter pname
whose value is a string p2
. I would like to read the value of p2
using pname
, something like $$pname
or ${$pname}
. Or in a more complicated way. If pnumber
is equal to 2
, then I would like to read the value of the parameter with name concat('p', $pnumber)
, something I would code asparam-value(concat('p', $pnumber))
.
Upvotes: 1
Views: 1275
Reputation: 7876
A portable workaround. If you control both the application and the stylesheet, you should pass the parameters as an xml document. Most processors give the option to make parameter a node-set. For example in MSXML I did it using:
xslProc.addParameter("params", xmlParams)
where xslProc
is of processor type, created from "Msxml2.XSLTemplate.6.0"
using createProcessor
method and xmlParams
is DomDocument
. Inside the stylesheet I was accesing my parameters using something like that:
<xsl:variable name="value">
<xsl:value-of select="$params//*[name() = concat('p', $pnumber)]" />
</xsl:variable>
If the processor does not support node-set external parameters, one may always combine the parameters with the data in one xml document. This works well in memory. If access to external files is possible, one may use document('params.xml')
syntax to access the parameters stored in a separate file.
I was also looking for a possibility to parse xml string and have a node-set of it, but it is seems to be available only as an extension in some xslt 2.0 parsers. I wanted 1.0 solution.
Upvotes: 0
Reputation: 7876
In libxslt
the thing is possible through dyn:evaluate
extension. Here is the description. There is total of 3 processors mentioned which are said to support this function:
Upvotes: 0
Reputation: 243529
This is possible whenthe XSLT stylesheet accesses itself as a regular XML document:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:param name="p1" select="'P1-Value'"/>
<xsl:param name="p2" select="'P2-Value'"/>
<xsl:param name="p3" select="'P3-Value'"/>
<xsl:param name="pName" select="'p3'"/>
<xsl:param name="pNumber" select="2"/>
<xsl:variable name="vDoc" select="document('')"/>
<xsl:template match="/">
<xsl:value-of select=
"concat('Param with name ',
$pName,
' has value: ',
$vDoc/*/xsl:param[@name = $pName]/@select
)"/>
<xsl:text>
</xsl:text>
<xsl:variable name="vParam" select=
"$vDoc/*/xsl:param[@name = concat('p', $pNumber)]"/>
<xsl:value-of select=
"concat('Param with name p',
$pNumber,
' has value: ',
$vParam/@select
)"/>
</xsl:template>
</xsl:stylesheet>
produces the wanted result:
Param with name p3 has value: 'P3-Value'
Param with name p2 has value: 'P2-Value'
Explanation:
The expression document('')
selects the document node of the current XSLT stylesheet.
A limitation is that the current XSLT stylesheet must have (be accessible via) a URI (such as residing at a given file and accessible by its filename) -- the above code doesn't produce a correct result if the stylesheet is dynamically generated (a string in memory).
Upvotes: 1