Re: [xsl] Converting a string to node test

Subject: Re: [xsl] Converting a string to node test
From: Xavier Cazin <cazinx@xxxxxxxxx>
Date: 22 Apr 2001 11:47:48 +0200
On Sat, 21 Apr 2001, davidc@xxxxxxxxx wrote:
> 
>> Do you know the secret?
> this is a FAQ I think.

Argh. This is the kind of FAQ very hard to track (in which section(s) should
it fall?)

>>   <xsl:copy-of select="$x[@$y=$z]/node()"/>
> 
> @$y doesn't mean anything as you observed.
> 
> If $y is a string with a name of an attribute then you can go
>   <xsl:copy-of select="$x[@*[name()=$y and .=$z]]/node()"/>

Another nice version of Jeni's solution, thank you! It seems so simple once
someone shows you :-)

> but usually it's more fun to pass in the node you want rather than 
> mess with names. Variables in XSLT are not restricted to strings
> so you can pass nodes around.
>
> You didn't show how you were calling your template but rather than pass
> <xsl:with-param name="x" select="foo"/>
> <xsl:with-param name="y" select="'attr'"/>
>
> you may be able to do
> 
> <xsl:with-param name="x" select="foo"/>
> <xsl:with-param name="y" select="foo[@attr']/>

I like this solution, but I'm not sure it is easy to implement for me,
since I wanted the various parameters to come from different documents,
one of them being a configuration file. The variable y rather acts as a key
in the config file. 

In case you are interested, here the relevant excerpt of the config file:

  <preferred-order criterium="location">
    <value>default</value>
    <value>work</value>
    <value>home</value>
    <value when="travelling">transit</value>
  </preferred-order>

The higher level call to the template (x becomes item and y becomes
criterium):

    <xsl:variable name="selected-addresses">
      <xsl:call-template name="preferred-item">
        <xsl:with-param name="item" select="address"/>
        <xsl:with-param name="criterium" select="'location'"/>
      </xsl:call-template>
    </xsl:variable>
 
And the recursive (wannabe generic) template itself:

  <xsl:template name="preferred-item">
    <xsl:param name="item"/>
    <xsl:param name="criterium"/>
    <xsl:param name="criterium-rank" select="1"/>

    <xsl:variable name="current-preferred-criterium" select="$config-tree/preferred-order[@criterium=$criterium]/value[$criterium-rank]"/>

    <xsl:variable name="hit">
    <!-- Here was the problem you solved -->
      <xsl:copy-of 
        select="$item[@*[local-name() = $criterium] = $current-preferred-criterium]/node()"/>
    </xsl:variable>

    <xsl:if test="not(xt:node-set($hit)/node())"><!-- nothing found ? -->
      <xsl:call-template name="preferred-item">
        <xsl:with-param name="item" select="$item"/>
        <xsl:with-param name="criterium" select="$criterium"/>
        <xsl:with-param 
          name="criterium-rank" select="$criterium-rank + 1"/>
      </xsl:call-template>
    </xsl:if>

    <xsl:copy-of select="$hit"/>

  </xsl:template>

If you see a way to make this a three lines template, please be diplomatic,
as I spend more hours on this that I expected :-))

Anyway, thanks again!

Xavier.


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread