xsl-list
[Top] [All Lists]

Re: calculating pow of numbers and a final sum

2003-01-22 03:07:43
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