RE: [xsl] Tabluation via XSLT.

Subject: RE: [xsl] Tabluation via XSLT.
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Wed, 4 Apr 2007 10:12:00 +0100
Your basic approach doesn't seem wrong to me (or procedural). But the code
can be simplified a lot, for example I think you can replace:

     <xsl:variable name="current_col" select="."/>
     <!-- only choose the ratings where it exists against the row currently
being processed -->
     <xsl:for-each select="$col_rating">
      <xsl:choose>
       <xsl:when test=".//@name=$current_col">
        <xsl:value-of select=".//@rating"/>
       </xsl:when>
      </xsl:choose>
     </xsl:for-each>

by

<xsl:for-each select="$col_rating[@name=current()]">
  <xsl:value-of select="@rating"/>
</xsl:for-each>

Michael Kay
http://www.saxonica.com/ 

> -----Original Message-----
> From: Furry Pop [mailto:furrypop@xxxxxxxxx] 
> Sent: 04 April 2007 09:55
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: [xsl] Tabluation via XSLT.
> 
> Hi,
>  
> I've got an XML document that I wish to convert into an HTML 
> table.  It requires further transformation by some third 
> party XSL libraries, which I will include in my XSLT and call 
> their templates with modes to do their clever stuff.
>  
> My approach so far has been rather procedural, and I have had 
> to use variables, etc to maintain state.  For instance, I use 
> a key to remove duplicates from the items to form the column 
> headings and then cycle through each row, matching against 
> the XML via the key.  Each row is sorted in order to keep it 
> aligned with the column headings. The problem with this is 
> that, particularly with the column headers, I lose sight of 
> the original XML structure, thereby preventing me from 
> applying further templates and using the mode functionality.
>  
> Is there a more declarative approach to this processing 
> wherein I can build the column headings without using 
> variables and then populate each row in the knowledge that 
> the appropriate item is being inserted into the appropriate 
> column?  I'm thinking of some better use of apply-templates 
> or some clever recursion but I can't see how to do it.
>  
> A much simplified version of source file and my sample XSLT 
> look something like the following:-
>  
> SOURCE FILE:-
> [code]
> <?xml version="1.0" encoding="UTF-8"?>
> <container>
>  <item>
>   <value name="arthur">
>    <item>
>     <value rating="X" name="joyce"/>
>     <value rating="W" name="ida"/>
>    </item>
>   </value>
>  </item>
>  <item>
>   <value name="bertrand">
>    <item>
>     <value rating="Y" name="ida"/>
>    </item>
>   </value>
>  </item>
>  <item>
>   <value name="colin">
>    <item>
>     <value rating="Z" name="joyce"/>
>    </item>
>   </value>
>  </item>
>  <item>
>   <value name="derek">
>    <item>
>     <value rating="X" name="joyce"/>
>    </item>
>   </value>
>  </item>
>  <item>
>   <value name="edward">
>    <item>
>     <value rating="Y" name="hilda"/>
>     <value rating="W" name="joyce"/>
>    </item>
>   </value>
>  </item>
>  <item>
>   <value name="frederick">
>    <item>
>     <value rating="Z" name="ida"/>
>    </item>
>   </value>
>  </item>
> </container>
> [/code]
>  
> XSLT:-
> [code]
> <xsl:stylesheet version="1.0"
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
> xmlns:fo="http://www.w3.org/1999/XSL/Format";>
>  <xsl:output method="html"/>
>  <xsl:key name="distinct-col"
> match="container/item/value/item/value/@name"
> use="."/>
>  <!-- store unique (ie "distinct") column headings for use 
> later-->  <xsl:variable name="cols"
> select="container/item/value/item/value/@name[generate-id()=ge
> nerate-id(key('distinct-col',.))]"/>
>  <xsl:template match="/">
>   <html>
>    <head>
>     <title>TEST CODE FOR TABULATION</title>
>    </head>
>    <body>
>     <table>
>      <tr>
>       <td class="rowtitle" />
>       <!-- set the column headings -->
>       <xsl:for-each select="$cols">
>        <xsl:sort/>
>        <td class="coltitle">
>         <xsl:value-of select="."/>
>        </td>
>       </xsl:for-each>
>      </tr>
>      <!-- create the rows -->
>      <xsl:apply-templates
> select="container/item/value">
>       <xsl:sort/>
>      </xsl:apply-templates>
>     </table>
>    </body>
>   </html>
>  </xsl:template>
>  <xsl:template match="container/item/value">
>   <tr>
>    <td class="rowtitle">
>     <xsl:value-of select=".//@name"/>
>    </td>
>    <!-- squirrel away the tree of ratings under the row 
> currently being processed -->
>    <xsl:variable name="col_rating"
> select="item/value"/>
>    <!-- display the rating for each col (the latter sorted in 
> line with the column headings above) -->
>    <xsl:for-each select="$cols">
>     <xsl:sort/>
>     <td>
>      <!-- squirrel away the col currently being viewed
> -->
>      <xsl:variable name="current_col" select="."/>
>      <!-- only choose the ratings where it exists against the 
> row currently being processed -->
>      <xsl:for-each select="$col_rating">
>       <xsl:choose>
>        <xsl:when test=".//@name=$current_col">
>         <xsl:value-of select=".//@rating"/>
>        </xsl:when>
>       </xsl:choose>
>      </xsl:for-each>
>     </td>
>    </xsl:for-each>
>   </tr>
>  </xsl:template>
> </xsl:stylesheet>
> [/code]
>  
> Thanks for any help,
>  
> J.
>  
> XSL Processor = Altova XMLSpy 2007 Professional
> 
> ________________________________________________
> F.Pop Esq is currently trading under the moniker 
> -> DRAWING PIN <-
> http://drawingpin.iuma.com 
> 
> Always trying to pin me down. 
> Why a title for your sound?
> 
> 
> 
> 
> 		
> ___________________________________________________________
> To help you stay safe and secure online, we've developed the 
> all new Yahoo! Security Centre. http://uk.security.yahoo.com

Current Thread