xsl-list
[Top] [All Lists]

RE: [xsl] Tabluation via XSLT.

2007-04-04 02:12:19
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[(_at_)name=current()]">
  <xsl:value-of select="@rating"/>
</xsl:for-each>

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

-----Original Message-----
From: Furry Pop [mailto:furrypop(_at_)yahoo(_dot_)com] 
Sent: 04 April 2007 09:55
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
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

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: 
<mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--



--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--