Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Logic in apply-templates in master-detail siblings

Status
Not open for further replies.

Chris2010

Programmer
Sep 6, 2005
2
GB
Logic in apply-templates

I am experimenting with the code written in thread XML sums and loops by GavinP1983 by extending the report to analyse more details so that I can understand how the logic works. So I am trying to get:

Year
Month
Store
Details here
[Store total]
[Month total]
[Year total]
[Grand total]

All the summaries work fine. They total up as expected. The problem comes when the "Details here" part is displayed. I only get detail where the store changes from month to month. If the month changes, but the store does not, I only get detail for the first store.

I have coded output to show what the logic parameters are along the way, and the logic looks good. The error in my example data is when the month changes from 6 to 7 but the store stays as "Bluewater". If I change the data in month 7 to be "Bluewater2" everything works ok, but hides where the real problem is. I also noticed that the "preceding-sibling" info showed Bath for Month 7 when I thought it should be "Bluewater". So I now really don't know whats going on.

Can anyone shed any light on how the logic is working? I thought it might be a bug in the processor but being new to this, I figured I'm doing something stupid.

My XSL is:
Code:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform">[/URL]
  <xsl:template match="/">
    <html>
      <head>
        <title>XML Sum and Loops</title>
        <style type="text/css">
caption
{
  font-size: large;
  font-weight: bold;
  text-align: left;
}
caption2
{
  font-size: large;
  text-align: left;
}
        </style>
      </head>
      <body>
        <table border="0" cellspacing="10" width="100%" summary="Complete data">
        <thead>
          <tr valign="top">
            <th align="left">Year</th>
            <th align="left">Month</th>
            <th align="left">Store<br/>Sender</th>
            <!--<th align="left">Sender</th>-->
            <th align="left"><br/>Customer</th>
            <th align="left"><br/>Address</th>
            <th align="left"><br/>Reason</th>
            <th align="left"><br/>Gift</th>
            <th align="right"><br/>Value</th>
          </tr>
        </thead>
        <tfoot>
		  <tr>
			<td colspan="8">
			  <hr/>
			</td>
		  </tr>
          <tr>
            <td colspan="7" align="right">Grand Total:</td>
            <td align="right">
              <xsl:value-of select="sum(NewDataSet/Table/Value)"/>
            </td>
          </tr>
        </tfoot>
      <tbody>
        
        <xsl:apply-templates select="NewDataSet/Table[not((Year = preceding-sibling::Table/Year))]" mode="Year"/>
        
      </tbody>
      </table>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="Table" mode="Year">
    <!--Apply templates to select for current year-->
    
    <tr><td colspan="8">Level=Year;<xsl:value-of select="Year"/>;<xsl:value-of select="Month"/>;<xsl:value-of select="Store"/></td></tr>
    <tr><td colspan="8">Preceding;<xsl:value-of select="preceding-sibling::Table/Year"/>;<xsl:value-of select="preceding-sibling::Table/Month"/>;<xsl:value-of select="preceding-sibling::Table/Store"/></td></tr>
    <tr><td colspane="8">selecting where Year[<xsl:value-of select="Year"/>]=current()/Year[<xsl:value-of select="current()/Year"/>] and not (Month[<xsl:value-of select="Month"/>]=preceding-sibling::Table/Month[<xsl:value-of select="preceding-sibling::Table/Month"/>])</td></tr>
    <xsl:apply-templates select="../Table[(Year = current()/Year)and not ((Month = preceding-sibling::Table/Month))]" mode="Month"/>
    
    <tr>
      <td colspan="7" align="right">
        <xsl:value-of select="concat(Year, ' total: ')"/>
      </td>
      <td align="right">
		<xsl:value-of select="sum(../Table[Year = current()/Year]/Value)"/>
      </td>
    </tr>
  </xsl:template>
  
  <xsl:template match="Table" mode="Month">
	<!--apply templates for detail here-->
    
    <tr><td colspan="8">Level=Month;<xsl:value-of select="Year"/>;<xsl:value-of select="Month"/>;<xsl:value-of select="Store"/></td></tr>
    <tr><td colspan="8">Preceding:;<xsl:value-of select="preceding-sibling::Table/Year"/>;<xsl:value-of select="preceding-sibling::Table/Month"/>;<xsl:value-of select="preceding-sibling::Table/Store"/></td></tr>
    <tr><td colspane="8">selecting where Year[<xsl:value-of select="Year"/>]=current()/Year[<xsl:value-of select="current()/Year"/>] and Month[<xsl:value-of select="Month"/>]=current()/Month[<xsl:value-of select="current()/Month"/>] and not (Store[<xsl:value-of select="Store"/>]=preceding-sibling::Table/Store[<xsl:value-of select="preceding-sibling::Table/Store"/>])</td></tr>
    <xsl:apply-templates select="../Table[(Year = current()/Year) and (Month = current()/Month) and not (Store = preceding-sibling::Table/Store)]" mode="Store"/>
    
	<tr>
	  <td colspan="6">
	  </td> 
	  <td align="right">
	    <xsl:value-of select="concat(Month, '-', Year, ' total: ')"/>
	  </td>
	  <td align="right">
	    <xsl:value-of select="sum(../Table[Year=current()/Year and Month=current()/Month]/Value)"/>
	  </td>
	</tr>
  </xsl:template>
  
  <xsl:template match="Table" mode="Store">
	<tr>
	  <td>
	    <b><xsl:value-of select="Year"/></b>
	  </td>
	  <td>
	    <b><xsl:value-of select="Month"/></b>
	  </td>
	  <td align="left">
	    <b><xsl:value-of select="Store"/></b>
	  </td>
	  <td colspan="5">
	  </td>
	</tr>
	<!--apply templates for detail here-->
    <tr><td colspan="8">Level=Store;<xsl:value-of select="Year"/>;<xsl:value-of select="Month"/>;<xsl:value-of select="Store"/></td></tr>
    <tr><td colspan="8">Preceding:;<xsl:value-of select="preceding-sibling::Table/Year"/>;<xsl:value-of select="preceding-sibling::Table/Month"/>;<xsl:value-of select="preceding-sibling::Table/Store"/></td></tr>
    <tr><td colspane="8">selecting where Year[<xsl:value-of select="Year"/>]=current()/Year[<xsl:value-of select="current()/Year"/>] and Month[<xsl:value-of select="Month"/>]=current()/Month[<xsl:value-of select="current()/Month"/>] and Store[<xsl:value-of select="Store"/>]=current()/Store[<xsl:value-of select="current()/Store"/>]</td></tr>
    <xsl:apply-templates select="../Table[(Year = current()/Year)and(Month=current()/Month) and (Store = current()/Store)]" mode="Details"/>
    
	<tr>
	  <td colspan="6">
	  </td> 
	  <td align="right">
	    <b><xsl:value-of select="concat(Store, ' total: ')"/></b>
	  </td>
	  <td align="right">
	    <b><xsl:value-of select="sum(../Table[Year=current()/Year and Month=current()/Month and Store=current()/Store]/Value)"/></b>
	  </td>
	</tr>
  </xsl:template>
  
  <xsl:template match="Table" mode="Details">
    <tr>
      <td colspan="2">
      </td>
      <td>
        <xsl:value-of select="Sender"/>
      </td>
      <td>
        <xsl:value-of select="Customer"/>
      </td>
      <td>
        <xsl:value-of select="Address"/>
      </td>
      <td>
        <xsl:value-of select="Reason"/>
      </td>
      <td>
        <xsl:value-of select="Gift"/>
      </td>
      <td align="right">
        <xsl:value-of select="Value"/>
      </td>
    </tr>
  </xsl:template>
</xsl:stylesheet>

My data is
Code:
<?xml version='1.0'?>
<?xml-stylesheet type="text/xsl" href="stylesheet.xsl"?>
<NewDataSet>
  <Table>
    <Year>2005</Year>
    <Month>6</Month>
    <Store>Bath</Store>
    <Reason>Repair Issue</Reason>
    <Sender>G. Best</Sender>
    <Customer>Miss Customer</Customer>
    <Address>1  Warminster Road, England</Address>
    <Gift>O1008 - Starlight Bouquet</Gift>
    <Value>10.00</Value>
  </Table>
  <Table>
    <Year>2005</Year>
    <Month>6</Month>
    <Store>Bluewater</Store>
    <Reason>Customer Service</Reason>
    <Sender>F. Flintstone</Sender>
    <Customer>Mr  Marshall</Customer><Address>35 Elton avenue sidcup</Address>
    <Gift>O7309 - Semillon Chardonnay - Sacred Hill</Gift>
    <Value>10.00</Value>
  </Table>
  <Table>
    <Year>2005</Year>
    <Month>6</Month>
    <Store>Bluewater</Store>
    <Reason>Billing Issue</Reason>
    <Sender>J. Bailey</Sender>
    <Customer>Mr HALLS</Customer>
    <Address>4, RENTON CLOSE WEST NEWBIGGIN SEVENOAKS KENT</Address>
    <Gift>O7309 - Semillon Chardonnay - Sacred Hill</Gift>
    <Value>10.00</Value>
  </Table>
  <Table>
    <Year>2005</Year>
    <Month>7</Month>
    <Store>Bluewater</Store>
    <Reason>Other</Reason>
    <Sender>C. Bluestone</Sender>
    <Customer>Mr  Blair</Customer>
    <Address>10 Uping Street, London</Address>
    <Gift>O7309 - Semillon Chardonnay - Sacred Hill</Gift>
    <Value>10.00</Value>
  </Table>
  <Table>
    <Year>2005</Year>
    <Month>7</Month>
    <Store>Bluewater</Store>
    <Reason>Delay in resolving complaint</Reason>
    <Sender>B. Rubble</Sender>
    <Customer>Mr J. Ross</Customer>
    <Address>282 Cramlington Way Swanley Kent</Address>
    <Gift>O7309 - Semillon Chardonnay - Sacred Hill</Gift>
    <Value>10.00</Value>
  </Table>
  <Table>
    <Year>2006</Year>
    <Month>1</Month><Store>Gateshead</Store>
    <Reason>Delay in resolving complaint</Reason>
    <Sender>E. Clark</Sender>
    <Customer>Mr M. Shaw</Customer>
    <Address>2 Garden Place Penshaw</Address>
    <Gift>O7309 - Semillon Chardonnay - Sacred Hill</Gift>
    <Value>10.00</Value>
  </Table>
  <Table>
    <Year>2006</Year>
    <Month>1</Month><Store>Gateshead</Store>
    <Reason>Delay in resolving complaint</Reason>
    <Sender>C. Taylor</Sender>
    <Customer>Miss E.B.M. Sommer</Customer>
    <Address>18 Lothian Road Middlesbrough</Address>
    <Gift>O7309 - Semillon Chardonnay - Sacred Hill</Gift>
    <Value>10.00</Value>
  </Table>
</NewDataSet>

My working data is
Code:
<?xml version='1.0'?>
<?xml-stylesheet type="text/xsl" href="stylesheet.xsl"?>
<NewDataSet>
  <Table>
    <Year>2005</Year>
    <Month>6</Month>
    <Store>Bath</Store>
    <Reason>Repair Issue</Reason>
    <Sender>G. Best</Sender>
    <Customer>Miss Customer</Customer>
    <Address>1  Warminster Road, England</Address>
    <Gift>O1008 - Starlight Bouquet</Gift>
    <Value>10.00</Value>
  </Table>
  <Table>
    <Year>2005</Year>
    <Month>6</Month>
    <Store>Bluewater</Store>
    <Reason>Customer Service</Reason>
    <Sender>F. Flintstone</Sender>
    <Customer>Mr  Marshall</Customer><Address>35 Elton avenue sidcup</Address>
    <Gift>O7309 - Semillon Chardonnay - Sacred Hill</Gift>
    <Value>10.00</Value>
  </Table>
  <Table>
    <Year>2005</Year>
    <Month>6</Month>
    <Store>Bluewater</Store>
    <Reason>Billing Issue</Reason>
    <Sender>J. Bailey</Sender>
    <Customer>Mr HALLS</Customer>
    <Address>4, RENTON CLOSE WEST NEWBIGGIN SEVENOAKS KENT</Address>
    <Gift>O7309 - Semillon Chardonnay - Sacred Hill</Gift>
    <Value>10.00</Value>
  </Table>
  <Table>
    <Year>2005</Year>
    <Month>7</Month>
    <Store>Bluewater2</Store>
    <Reason>Other</Reason>
    <Sender>C. Bluestone</Sender>
    <Customer>Mr  Blair</Customer>
    <Address>10 Uping Street, London</Address>
    <Gift>O7309 - Semillon Chardonnay - Sacred Hill</Gift>
    <Value>10.00</Value>
  </Table>
  <Table>
    <Year>2005</Year>
    <Month>7</Month>
    <Store>Bluewater2</Store>
    <Reason>Delay in resolving complaint</Reason>
    <Sender>B. Rubble</Sender>
    <Customer>Mr J. Ross</Customer>
    <Address>282 Cramlington Way Swanley Kent</Address>
    <Gift>O7309 - Semillon Chardonnay - Sacred Hill</Gift>
    <Value>10.00</Value>
  </Table>
  <Table>
    <Year>2006</Year>
    <Month>1</Month>
    <Store>Gateshead</Store>
    <Reason>Delay in resolving complaint</Reason>
    <Sender>E. Clark</Sender>
    <Customer>Mr M. Shaw</Customer>
    <Address>2 Garden Place Penshaw</Address>
    <Gift>O7309 - Semillon Chardonnay - Sacred Hill</Gift>
    <Value>10.00</Value>
  </Table>
  <Table>
    <Year>2006</Year>
    <Month>1</Month>
    <Store>Gateshead</Store>
    <Reason>Delay in resolving complaint</Reason>
    <Sender>C. Taylor</Sender>
    <Customer>Miss E.B.M. Sommer</Customer>
    <Address>18 Lothian Road Middlesbrough</Address>
    <Gift>O7309 - Semillon Chardonnay - Sacred Hill</Gift>
    <Value>10.00</Value>
  </Table>
</NewDataSet>

The ouput for when the month changes, but the store does not is below. I have ***** where it is going wrong:
Year Month Store
Sender Customer Address Reason Gift Value

Level=Year;2005;6;Bath
Preceding;;;
selecting where Year[2005]=current()/Year[2005] and not (Month[6]=preceding-sibling::Table/Month[])

Level=Month;2005;6;Bath
Preceding:;;;
selecting where Year[2005]=current()/Year[2005] and Month[6]=current()/Month[6] and not (Store[Bath]=preceding-sibling::Table/Store[])

2005 6 Bath
Level=Store;2005;6;Bath
Preceding:;;;
selecting where Year[2005]=current()/Year[2005] and Month[6]=current()/Month[6] and Store[Bath]=current()/Store[Bath]

G. Best Miss Customer 1 Warminster Road, England Repair Issue O1008 - Starlight Bouquet 10.00
Bath total: 10

2005 6 Bluewater
Level=Store;2005;6;Bluewater
Preceding:;2005;6;Bath
selecting where Year[2005]=current()/Year[2005] and Month[6]=current()/Month[6] and Store[Bluewater]=current()/Store[Bluewater]
F. Flintstone Mr Marshall 35 Elton avenue sidcup Customer Service O7309 - Sem - Sacred Hill 10.00
J. Bailey Mr HALLS 4, RENTON CLOSE WEST NEENT Billing Issue O7309 - Sem - Sacred Hill 10.00
Bluewater total: 20
6-2005 total: 30

Level=Month;2005;7;Bluewater
Preceding:;2005;6;Bath
selecting where Year[2005]=current()/Year[2005] and Month[7]=current()/Month[7] and not (Store[Bluewater]=preceding-sibling::Table/Store[Bath])
*******HERE IS THE ERROR - Where is the data for Month 7 Bluewater?*******
7-2005 total: 20

2005 total: 50
Level=Year;2006;1;Gateshead
Preceding;2005;6;Bath
selecting where Year[2006]=current()/Year[2006] and not (Month[1]=preceding-sibling::Table/Month[6])
Level=Month;2006;1;Gateshead
Preceding:;2005;6;Bath
selecting where Year[2006]=current()/Year[2006] and Month[1]=current()/Month[1] and not (Store[Gateshead]=preceding-sibling::Table/Store[Bath])

2006 1 Gateshead
Level=Store;2006;1;Gateshead
Preceding:;2005;6;Bath
selecting where Year[2006]=current()/Year[2006] and Month[1]=current()/Month[1] and Store[Gateshead]=current()/Store[Gateshead]
E. Clark Mr M. Shaw 2 Garden Place Penshaw Delay O7309 - Sem - Sacred Hill 10.00
C. Taylor Miss E.B.M. Sommer 18 Lothian Road Middlesbrough Delay O7309 - Sem - Sacred Hill 10.00
Gateshead total: 20
1-2006 total: 20
2006 total: 20
 
I descovered a solution via another forum. Apparently using the Muenchian Method. The grouping keys are concatenated so if ever there is a change in either of them, the templates get applied. I've posted the solution below provided by a chap called Yuri. I thought it was pretty cool. If anyone has been trying to solve this one, thanks for your efforts anyway. If your solution is different, I'd still like to study it. I'm at that stage where I'm getting a buzz out of XSL. Maybe one day I'll be able to contribute my own work to this forum. Take care everyone. Chris

Code:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform">[/URL]
  <xsl:key name="year" match="Table" use="Year" />
  <xsl:key name="year-month" match="Table" use="concat(Year, '$', Month)" />
  <xsl:key name="year-month-store" match="Table" use="concat(Year, '$', Month, '$', Store)" />

  <xsl:template match="/">
    <html>
      <head>
        <title>XML Sum and Loops</title>
        <style type="text/css">
caption
{
  font-size: large;
  font-weight: bold;
  text-align: left;
}
caption2
{
  font-size: large;
  text-align: left;
}
        </style>
      </head>
      <body>
        <table border="0" cellspacing="10" width="100%" summary="Complete data">
        <thead>
          <tr valign="top">
            <th align="left">Year</th>
            <th align="left">Month</th>
            <th align="left">Store<br/>Sender</th>
            <!--<th align="left">Sender</th>-->
            <th align="left"><br/>Customer</th>
            <th align="left"><br/>Address</th>
            <th align="left"><br/>Reason</th>
            <th align="left"><br/>Gift</th>
            <th align="right"><br/>Value</th>
          </tr>
        </thead>
        <tfoot>
          <tr>
            <td colspan="8">
              <hr/>
            </td>
          </tr>
          <tr>
            <td colspan="7" align="right">Grand Total:</td>
            <td align="right">
              <xsl:value-of select="sum(NewDataSet/Table/Value)"/>
            </td>
          </tr>
        </tfoot>
      <tbody>
        
        <xsl:apply-templates select="NewDataSet/Table[generate-id() = generate-id(key('year', Year))]" mode="Year"/>
        
      </tbody>
      </table>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="Table" mode="Year">
    <xsl:apply-templates select="key('year', current()/Year)[generate-id() = generate-id(key('year-month', concat(Year, '$', 

Month)))]" mode="Month"/>
    
    <tr>
      <td colspan="7" align="right">
        <xsl:value-of select="concat(Year, ' total: ')"/>
      </td>
      <td align="right">
        <xsl:value-of select="sum(key('year', current()/Year)/Value)"/>
      </td>
    </tr>
  </xsl:template>
  
  <xsl:template match="Table" mode="Month">
    <xsl:apply-templates select="key('year-month', concat(current()/Year, '$', current()/Month))[generate-id() = 

generate-id(key('year-month-store', concat(Year, '$', Month, '$', Store)))]" mode="Store"/>

    <tr>
      <td colspan="6">
      </td> 
      <td align="right">
        <xsl:value-of select="concat(Month, '-', Year, ' total: ')"/>
      </td>
      <td align="right">
        <xsl:value-of select="sum(key('year-month', concat(current()/Year, '$', current()/Month))/Value)"/>
      </td>
    </tr>
  </xsl:template>
  
  <xsl:template match="Table" mode="Store">
    <tr>
      <td>
        <b><xsl:value-of select="Year"/></b>
      </td>
      <td>
        <b><xsl:value-of select="Month"/></b>
      </td>
      <td align="left">
        <b><xsl:value-of select="Store"/></b>
      </td>
      <td colspan="5">
      </td>
    </tr>
    
    <xsl:apply-templates select="key('year-month-store', concat(current()/Year, '$', current()/Month, '$', current()/Store))" 

mode="Details"/>
    
    <tr>
      <td colspan="6">
      </td> 
      <td align="right">
        <b><xsl:value-of select="concat(Store, ' total: ')"/></b>
      </td>
      <td align="right">
        <b><xsl:value-of select="sum(key('year-month-store', concat(current()/Year, '$', current()/Month, '$', 

current()/Store))/Value)"/></b>
      </td>
    </tr>
  </xsl:template>
  
  <xsl:template match="Table" mode="Details">
    <tr>
      <td colspan="2">
      </td>
      <td>
        <xsl:value-of select="Sender"/>
      </td>
      <td>
        <xsl:value-of select="Customer"/>
      </td>
      <td>
        <xsl:value-of select="Address"/>
      </td>
      <td>
        <xsl:value-of select="Reason"/>
      </td>
      <td>
        <xsl:value-of select="Gift"/>
      </td>
      <td align="right">
        <xsl:value-of select="Value"/>
      </td>
    </tr>
  </xsl:template>
</xsl:stylesheet>
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top