RE: [xsl] Show a column only if the total is not zero

Subject: RE: [xsl] Show a column only if the total is not zero
From: "Andrew Welch" <ajwelch@xxxxxxxxxxxxxxx>
Date: Tue, 18 May 2004 15:54:59 +0100
> > I would like the report on the project to look like
> > this.
> > 
> > name		fees		travel
> > Adam		134.25		39.25
> > Brian		172.50		52.75
> > Chris		103.75		0.00
> > Total		410.50		92.00
> > 
> > There was no overtime on this project so I don't
> > want it shown. I should
> > be most grateful for any suggestions on the best way
> > to show the columns
> > where the total is not zero. (In practice I have
> > more than 3 types of
> > cost.)


Here's my attempt - it indexes the xml on position (to group by column)
then for each cell checks the column for a number.

It using the fact that number(0.00) returns false (but will return true
if any in the sequence are positive), and 'not(. - 1)' will return true
when '.' is a string.  

I'm not happy with the 'not(. - 1)' so if anyone can point out a better
test that would be good.

This stylesheet:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>

<xsl:key name="cols" match="person/*"
use="count(preceding-sibling::*|.)"/>

<xsl:template match="/root">
  <table>
    <thead>
      <xsl:for-each select="person[1]/*">
        <xsl:if test="not(. - 1) or number(key('cols',position()))">
          <th><xsl:value-of select="local-name()"/></th>
        </xsl:if>
      </xsl:for-each>
    </thead>
    <tbody>
      <xsl:apply-templates/>
    </tbody>
  </table>
</xsl:template>

<xsl:template match="person">
  <tr>
    <xsl:for-each select="*">
      <xsl:if test="not(. - 1) or number(key('cols',position()))">
        <td><xsl:value-of select="."/></td>
      </xsl:if>
    </xsl:for-each>
  </tr>
</xsl:template>

</xsl:stylesheet>


Applied to this xml:

<root>
<person>
   <name>Adam</name>
   <fees>134.25</fees>
   <overtime>0.00</overtime>
   <travel>39.25</travel>
</person>
<person>
   <name>Brian</name>
   <fees>172.50</fees>
   <overtime>0.00</overtime>
   <travel>52.75</travel>
</person>
<person>
   <name>Chris</name>
   <fees>103.75</fees>
   <overtime>0.00</overtime>
   <travel>0.00</travel>
</person>
</root>

Gives this result:

<?xml version="1.0" encoding="UTF-8"?>
<table>
	<thead>
		<th>name</th>
		<th>fees</th>
		<th>travel</th>
	</thead>
	<tbody>
		<tr>
			<td>Adam</td>
			<td>134.25</td>
			<td>39.25</td>
		</tr>
		<tr>
			<td>Brian</td>
			<td>172.50</td>
			<td>52.75</td>
		</tr>
		<tr>
			<td>Chris</td>
			<td>103.75</td>
			<td>0.00</td>
		</tr>
	</tbody>
</table>

cheers
andrew

Current Thread