1

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 as
param-value(concat('p', $pnumber)).

2
  • The languages you refer to - bash, ant - are macro-based languages where nearly everything happens at run-time. XSLT isn't like that; it's much more like compiler-based languages (C/Java etc) where variable and function names are purely compile-time constructs. Commented Nov 3, 2012 at 16:17
  • @Michael, don't you think it could be an answer to this question? Who may give a better answer for "why" than you? :) Commented Nov 3, 2012 at 17:01

3 Answers 3

1

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>&#xA;</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).

Sign up to request clarification or add additional context in comments.

2 Comments

This is a solution for parameters, however limited to parameters whose value is not set from outside (command line, addParameter), right?
@Jarekczek: Correct. Parameter's dynamic value cannot be accessed in this way. There is no such thing as reflection in XSLT -- although using the above technique one can discover at run-time parameter and variables names, it isn't possible to find their dynamically assigned values -- and one reason for this is that in a functional language there is no notion of time -- when our code is executing there is no guarantee some particular code fragment (which assigned the value to the parameter) has already been executed.
0

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:

  • Xalan-J from Apache (version 2.4.1) and
  • 4XSLT, from 4Suite. (version 0.12.0a3)
  • libxslt from Daniel Veillard et al. (version 1.0.19)

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.