RE: [xsl] Tabluation via XSLT.2007-04-05 05:54:59Thanks, 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[(_at_)name=current()]"> <xsl:value-of select="@rating"/> </xsl:for-each> </td> </xsl:for-each> </tr> </xsl:template> </xsl:stylesheet> [/code] J. --- Michael Kay <mike(_at_)saxonica(_dot_)com> 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[(_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 convertinto an HTMLtable. It requires further transformation by somethirdparty XSL libraries, which I will include in myXSLT and calltheir templates with modes to do their cleverstuff.My approach so far has been rather procedural, andI have hadto use variables, etc to maintain state. Forinstance, I usea key to remove duplicates from the items to formthe columnheadings and then cycle through each row, matchingagainstthe XML via the key. Each row is sorted in orderto keep italigned with the column headings. The problem withthis isthat, particularly with the column headers, I losesight ofthe original XML structure, thereby preventing mefromapplying further templates and using the modefunctionality.Is there a more declarative approach to thisprocessingwherein I can build the column headings withoutusingvariables and then populate each row in theknowledge thatthe appropriate item is being inserted into theappropriatecolumn? I'm thinking of some better use ofapply-templatesor some clever recursion but I can't see how to doit.A much simplified version of source file and mysample XSLTlook 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 headingsfor uselater--> <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 underthe rowcurrently being processed --> <xsl:variable name="col_rating" select="item/value"/> <!-- display the rating for each col (thelatter sorted inline with the column headings above) --> <xsl:for-each select="$cols"> <xsl:sort/> <td> <!-- squirrel away the col currently beingviewed--> <xsl:variable name="current_col" select="."/> <!-- only choose the ratings where it existsagainst therow 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 --~------------------------------------------------------------------ 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> --~--
|
|