Subject: RE: [xsl] Tabluation via XSLT. From: Furry Pop <furrypop@xxxxxxxxx> Date: Thu, 5 Apr 2007 13:54:35 +0100 (BST) |
Thanks, Michael. Without wanting to appear obsequious, I found part of the solution in your book! ;-) I've changed the XSL to firstly make the change you suggested below and then to adjust the earlier loop that generates the column headings to make use of keys, as per an adaptation of the "Muenchian grouping" method. Here's the new XSL. Same output, but now the document context is retained; ergo I can apply modes to the formatting of the column headers. Very slightly clunky still, as I have to maintain two indexes. I can't seem to remove the need for "col-items" and generate "$cols" directly from "col-nodes", but will probably live with it. [code] <?xml version="1.0" encoding="UTF-8"?> <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="col-items" match="container/item/value/item/value/@name" use="."/> <xsl:key name="col-nodes" match="container/item/value/item/value" use="@name"/> <xsl:variable name="cols" select="container/item/value/item/value/@name[generate-id()=generate-id(key('col-items',.))]"/> <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="container/item/value/item/value[generate-id() = generate-id(key('col-nodes', @name)[1])]"> <xsl:sort select="@name" /> <td> <xsl:value-of select="@name" /> </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> <xsl:for-each select="$col_rating[@name=current()]"> <xsl:value-of select="@rating"/> </xsl:for-each> </td> </xsl:for-each> </tr> </xsl:template> </xsl:stylesheet> [/code] J. --- Michael Kay <mike@xxxxxxxxxxxx> wrote: > 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> > === message truncated === ________________________________________________ Always trying to pin me down. Why a title for your sound? ___________________________________________________________ What kind of emailer are you? Find out today - get a free analysis of your email personality. Take the quiz at the Yahoo! Mail Championship. http://uk.rd.yahoo.com/evt=44106/*http://mail.yahoo.net/uk
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
RE: [xsl] Tabluation via XSLT., Michael Kay | Thread | [xsl] Xsl:variable content should b, Alan Hale |
[xsl] Namespace'd XPath expression , Mohsen Saboorian | Date | Re: [xsl] Proposed syntax for names, Colin Adams |
Month |