Re: [xsl] calculating pow of numbers and a final sum

Subject: Re: [xsl] calculating pow of numbers and a final sum
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Wed, 22 Jan 2003 10:07:43 +0000
Hi Andreas,

> This is my XML:
>
> <?xml version="1.0" ?>
> <logging>
>   <target name="init"/>
>   <target name="debug"/>
>   <target name="fatal"/>
> </logging>
>
> this should result in:
>
> public static final int INIT = 1;
> public static final int DEBUG = 2;
> public static final int FATAL = 4;
> public static final int ALL = 8;
>
> I can get everything working except the numbers. How can I calculate
> the numbers which are something like counter=2^(pos-1)?

One method of getting this output would be to step through the
<target> elements one by one, passing a parameter for the counter as
you go. Something like:

<xsl:template match="logging">
  <xsl:apply-templates select="target[1]" />
</xsl:template>

<xsl:template match="target">
  <xsl:param name="counter" select="1" />
  <xsl:text>public static final int </xsl:text>
  <xsl:value-of select="translate(@name, $lc, $uc)" />
  <xsl:text> = </xsl:text>
  <xsl:value-of select="$counter" />
  <xsl:text>;&#xA;</xsl:text>
  <xsl:choose>
    <xsl:when test="following-sibling::target">
      <xsl:apply-templates select="following-sibling::target[1]">
        <xsl:with-param name="counter" select="$counter * 2" />
      </xsl:apply-templates>
    </xsl:when>
    <xsl:otherwise>
      <xsl:text>public static final int ALL = </xsl:text>
      <xsl:value-of select="$counter * 2" />
      <xsl:text>;</xsl:text>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

Another way would be to create a recursive template to calculate the
power of two and then do a simple loop over the targets:

<xsl:template match="logging">
  <xsl:for-each select="target">
    <xsl:text>public static final int </xsl:text>
    <xsl:value-of select="translate(@name, $lc, $uc)" />
    <xsl:text> = </xsl:text>
    <xsl:call-template name="power-of-two">
      <xsl:with-param name="power" select="position() - 1" />
    </xsl:call-template>
    <xsl:text>;&#xA;</xsl:text>
  </xsl:for-each>
</xsl:template>

You can get a general template to work out the power of a number from:

  http://www.exslt.org/math/functions/power/math.power.template.xsl

or write one specifically for powers of two, like:

<xsl:template name="power-of-two">
  <xsl:param name="power" select="0" />
  <xsl:param name="result" select="1" />
  <xsl:choose>
    <xsl:when test="$power = 0">
      <xsl:value-of select="$result" />
    </xsl:when>
    <xsl:otherwise>
      <xsl:call-template name="power-of-two">
        <xsl:with-param name="power" select="$power - 1" />
        <xsl:with-param name="result" select="$result * 2" />
      </xsl:call-template>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

Cheers,

Jeni

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


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


Current Thread