This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Re: A specific Transformation quesition
- To: <xsl-list at mulberrytech dot com>
- Subject: Re: A specific Transformation quesition
- From: "Steve Muench" <Steve dot Muench at oracle dot com>
- Date: Thu, 26 Oct 2000 19:28:21 -0700
- References: <00BB1956AE40D411B5B60050DA27311F121B7C@mail1.bluezone.net>
- Reply-To: xsl-list at mulberrytech dot com
Adam,
| I need some help figuring out how to do a somewhat complex transform (XML
| into HTML) that I need help with. Its essentially a cross-tab type
| situation.
Here's a stylesheet that produces the cross-product
you're looking for. It uses an <xsl:key> like functional
indexes to speed up the iteration of unique regions.
Assuming the input is:
<demo>
<salesman id="0001" name="Rick Peterson">
<account id="act001" region="Midwest">Johnosn's Laundry</account>
<account id="act002" region="Canada">Franks's Laundry</account>
<account id="act003" region="Alaska">Mary's Laundry</account>
<account id="act004" region="New Jersey">Bill's Laundry</account>
<account id="act005" region="Midwest">Hammond's Laundry</account>
</salesman>
<salesman id="0003" name="Ty Coon">
<account id="act006" region="Canada">Franks's Diner</account>
<account id="act007" region="Midwest">Johnosn's Diner</account>
<account id="act008" region="Canada">Hammond's Diner</account>
<account id="act009" region="Alaska">Mary's Diner</account>
<account id="act010" region="Alaska">Bill's Diner</account>
</salesman>
</demo>
The following stylesheet produces an HTML table crosstab
with salespeople down the left (ordered by name) and regions
across the top (ordered by name), with a grid cell for each
crosstab, and &nsbp; for empty cells.
<!-- Example of a "CrossTab" stylesheet using <xsl:key>'s for grouping -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="b" match="@region" use="."/>
<xsl:template match="/">
<html>
<body>
<table border="1" cellspacing="0">
<!-- Generate the row of table header cells -->
<tr>
<th>Salesperson</th>
<!--
| Generate a header cell for each unique region name
|
| See Chapter 9 of "Building Oracle XML Applications" from O'Reilly
| for a detailed explanation of how this <xsl:key> based technique works
+-->
<xsl:for-each select="//@region[generate-id(.)=generate-id(key('b',.)[1])]">
<!-- Sort by the region name (the value of the current @region attribute -->
<xsl:sort select="."/>
<th>
<xsl:value-of select="."/>
</th>
</xsl:for-each>
</tr>
<!-- Generate a row for each salesman -->
<xsl:for-each select="demo/salesman">
<!-- Sort by salesman name -->
<xsl:sort select="@name"/>
<!-- Keep the current salesman in a variable for later -->
<xsl:variable name="cur" select="."/>
<tr>
<!-- First cell has the salesman's name -->
<td bgcolor="yellow"><xsl:value-of select="@name"/></td>
<!-- Generate a cell for each unique region -->
<xsl:for-each select="//@region[generate-id(.)=generate-id(key('b',.)[1])]">
<td>
<!-- If no accts for current salesman in current region, do -->
<xsl:if test="not($cur/account[@region=current()])"> </xsl:if>
<!-- List matching accounts for current salesman in current region -->
<xsl:for-each select="$cur/account[@region=current()]">
<xsl:value-of select="."/>
<xsl:if test="position() != last()"><br/></xsl:if>
</xsl:for-each>
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
______________________________________________________________
Steve Muench, Lead XML Evangelist & Consulting Product Manager
BC4J & XSQL Servlet Development Teams, Oracle Rep to XSL WG
Author "Building Oracle XML Applications", O'Reilly
http://www.oreilly.com/catalog/orxmlapp/
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list