RE: [xsl] Transform min and max values to list?

Subject: RE: [xsl] Transform min and max values to list?
From: "Xuegen Jin" <xjin_imi@xxxxxxxxx>
Date: Thu, 19 Apr 2001 11:10:21 -0400
Wow, that is enlightening. Are there a list of such tricks documented
somewhere on the net? :-)

-----Original Message-----
From: owner-xsl-list@xxxxxxxxxxxxxxxxxxxxxx
[mailto:owner-xsl-list@xxxxxxxxxxxxxxxxxxxxxx]On Behalf Of Jeni Tennison
Sent: Thursday, April 19, 2001 8:00 AM
To: Michael Strasser
Cc: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: Re: [xsl] Transform min and max values to list?


Hi Michael,

> I want to transform this element:
>
> <number min="1" max="3"/>
>
> into this:
>
> <select>
>   <option>1</option>
>   <option>2</option>
>   <option>3</option>
> </select>
>
> I have looked at for-each but its select attribute requires a node-set. Is
> there a simple way to achieve what I want?

Well, you could be terribly virtuous and use recursive templates.
Have a template that creates the option element, taking a $number
parameter (the number for the option) and a $max parameter (the
maximum number that should be outputted.  Use the $number to create
the value of the option, and test the $max parameter to see whether
you should move on to the next one:

<xsl:template name="create-option">
   <xsl:param name="number" select="1" />
   <xsl:param name="max" select="1" />
   <option><xsl:value-of select="$number" /></option>
   <xsl:if test="$number &lt; $max">
      <xsl:call-template name="create-option">
         <xsl:with-param name="number" select="$number + 1" />
         <xsl:with-param name="max" select="$max" />
      </xsl:call-template>
   </xsl:if>
</xsl:template>

You can then call this template from the number-matching template,
with the @min attribute giving the starting $number, and the @max
attribute giving the $max parameter:

<xsl:template match="number">
   <select>
      <xsl:call-template name="create-option">
         <xsl:with-param name="number" select="@min" />
         <xsl:with-param name="max" select="@max" />
      </xsl:call-template>
   </select>
</xsl:template>

So, that's the virtuous way.  However, you can employ the Piez 'cheap
hack' method (his words, not mine), and use xsl:for-each instead.  All
you need to do is construct a node set that consists of the right
number of nodes, and then iterate over them.  You can use the
position() of the node you're looking at as the basis of the number
you put in the option.  One method would be:

<xsl:variable name="random-nodes" select="document('')//*" />
<xsl:template match="number">
   <xsl:variable name="min" select="@min" />
   <xsl:variable name="nnodes" select="(@max - @min) + 1" />
   <select>
      <xsl:for-each select="$random-nodes[position() &lt;= $nnodes]">
         <option>
            <xsl:value-of select="position() + $min - 1" />
         </option>
      </xsl:for-each>
   </select>
</xsl:template>

I hope that helps,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/



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


_________________________________________________________
Do You Yahoo!?
Get your free @yahoo.com address at http://mail.yahoo.com


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


Current Thread