Question

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

Was it helpful?

Solution

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

OTHER TIPS

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>

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top