Jarekczek
Jarekczek

Reputation: 7876

Indirect variable/parameter reference (name in another property / another variable)

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)).

Upvotes: 1

Views: 1275

Answers (3)

Jarekczek
Jarekczek

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

Jarekczek
Jarekczek

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:

  • 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)

Upvotes: 0

Dimitre Novatchev
Dimitre Novatchev

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

Upvotes: 1

Related Questions