tags:

views:

2004

answers:

3

Hi,

I'm passing in a bunch of key-value pairs as parameters to a XSL (date -> "20th January", author -> "Dominic Rodger", ...).

These are referenced in some XML I'm parsing - the XML looks like this:

<element datasource="date" />

At present, I can't work out how to get 20th January out of these except with a horrible <xsl:choose> statement:

<xsl:template match="element">
  <xsl:choose>
    <xsl:when test="@datasource = 'author'">
      <xsl:value-of select="$author" />
    </xsl:when>
    <xsl:when test="@datasource = 'date'">
      <xsl:value-of select="$date" />
    </xsl:when> 
    ...
  </xsl:choose>
</xsl:template>

I'd like to use something like:

<xsl:template match="element">
  <xsl:value-of select="${@datasource}" />
</xsl:template>

But I suspect this isn't possible. I'm opening to using external function calls, but want to avoid having to enumerate all possible map keys in my XSL. Any ideas?

Thanks,

Dom

A: 

How about

<xsl:template match="date-element">
  <xsl:text>${date}</xsl:text>
</xsl:template>

i.e. instead of using an attribute, match using different element names.

If you can't change the source XML, run it through a small XSLT that converts the attributes to the correct element names.

A different solution would be putting the xsl:param elements into a different XML document (or try to make the XSLT template read itself again). Then you can use xsl:key and key() to reference them.

[EDIT] Replaced xsl:value-of with xsl:text. I don't have an XSLT util handy, so I can't test this. Please post a comment if this doesn't work either.

Aaron Digulla
Sorry, but the "select" attribute is the only one for which AVTs (Attribute-value-templates) cannot be specified.
Dimitre Novatchev
+1  A: 

Here is one possible solution, however I'd recommend grouping all parameters in a separate XML file and accessing them with the document() function:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common"
 exclude-result-prefixes="ext"
 >
 <xsl:output method="text"/>

 <xsl:param name="date" select="'01-15-2009'"/>
 <xsl:param name="author" select="'Dominic Rodger'"/>
 <xsl:param name="place" select="'Hawaii'"/>
 <xsl:param name="time" select="'midnight'"/>

 <xsl:variable name="vrtfParams">
   <date><xsl:value-of select="$date"/></date>
   <author><xsl:value-of select="$author"/></author>
   <place><xsl:value-of select="$place"/></place>
   <time><xsl:value-of select="$time"/></time>
 </xsl:variable>

 <xsl:variable name="vParams" select="ext:node-set($vrtfParams)"/>

    <xsl:template match="element">
      <xsl:value-of select=
       "concat('&#xA;', @datasource, ' = ',
               $vParams/*[name() = current()/@datasource]
               )"
       />
    </xsl:template>
</xsl:stylesheet>

When this transformation is applied on the following XML document:

<data>
  <element datasource="date" />
  <element datasource="place" />
</data>

the correct result is produced:

date = 01-15-2009

place = Hawaii

Do note the use of the xxx:node-set() function (the EXSLT one is used here) to convert an RTF (Result Tree Fragment) to a regular xml document (temporary tree).

Dimitre Novatchev
A: 

If your @datasource always matches the parameter name, you can try the "evaluate" function. Note: this code is untested.

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:exslt-dynamic="http://exslt.org/dynamic"
>

<xsl:param name="date"/>

<xsl:template match="element">
  <xsl:value-of select="exslt-dynamic:evaluate('$' + @datasource)"/>
</xsl:template>

</xsl:stylesheet>
Adam J.R. Erickson
It is untested, indeed. In XPath one cannot sum ('+') strings -- this would never even compile.
Dimitre Novatchev