Subject: Re: [xsl] Create Table From: "Eric J. Bowman" <eric@xxxxxxxxxxxxxxxx> Date: Tue, 6 Apr 2010 19:23:12 -0600 |
bernie bonn wrote: > > So I have my table built with all the source changes, now I want to > add a row with the 'diffs' for each change... > I'm pretty sure you meant to say you want to add a *column* with the relevant diffs... ;-). > > Off topic, I plan on using JavaScript to hide the diff detail unless > user wants to see it. > Not off-topic at all. You want the new column to be optional, OK. I'm assuming you'll be calling this transformation from Javascript, rather than an xml-stylesheet PI, if you want to present the user with options for the <table> content, to keep the diffs transformation from executing -- otherwise you could just toggle the column by setting a <col> tag to display:none. I added a global boolean parameter to the stylesheet, defaulting to true and executing the code for transforming the optional column. This may be overridden easily when the transform is called by Javascript, in any browser -- executing a stylesheet with a parameter is pretty standard stuff. With an xml-stylesheet PI, though, only mozilla has a proprietary mechanism to allow parameter passing. > > The challenge is after i have grabbed the the File, version, date > etc for the first row, I need to then somehow grab all the data > nodes where @field=diff, until the next node where @field!=diff, and > place it in the next row. Seems like a while loop, but I know those > don't exist. > You just need to think upside-down, in terms of document order. Instead of checking against some value for the *next* node, look for patterns in *previous* nodes. This makes recursive design easier, IMHO. Instead of looping through a set until some condition is met, think in terms of selecting a set which meets certain criteria. In this case, we need to select all the following-sibling data elements with @section=diff before the next <tr> delimiter, but which don't have a preceding-sibling where @section!=diff. This is a two-step operation which requires us to first identify a nodeset of all @section=diff between the delimiters, by using <variable><copy-of/></variable>. We can then perform operations against that variable of type=nodeset, instead of the document as a whole. This makes it easy to then process only the data elements we're interested in. If we're only ever searching up the preceding-sibling axis, then we don't need to account for end-of-parent-element, which is what I mean by thinking upside-down. Notice I've rolled the xsl:stylesheet @version up to '1.1'. I don't know the story on browser compatibility with XSLT 1.0 vs. 1.1, but I do know that all XSLT-enabled browsers grok exslt:node-set(), so if my code doesn't work in your target browser you can alter it to use exslt: node-set() and it ought to work. As I said before, XSLT 1 forces one to be clever. I wouldn't normally code a double-negative as I have here, but the key logic turned out to be checking that something is not(!=). It's a bit counter-intuitive, which is why this response took so long -- I got totally stumped on it until today. Further comments in the XSLT code. > > Sorry this is so muddled, let me know if you need clarifications. > Thanks again, > The only apologizing needed here, is from whoever designed the XML source language you're working with. After receiving fifty lashes with a wet noodle. Just sayin'. -Eric <?xml version='1.0' encoding='utf-8'?> <interface-categories> <data lineId='1' section='diff' field='diff'>if (reportService = null)</data> <data lineId='2' section='diff' field='diff'>return false;</data> <data lineId='3' section='diff' field='diff'>return true;</data> <data lineId='4' section='changes' field='version'>\main\spr2010_apr_dev\2</data> <data lineId='5' section='changes' field='date'>20100310.102844</data> <data lineId='6' section='changes' field='user'>jryan</data> <data lineId='7' section='changes' field='cr_number'>602018</data> <data lineId='8' section='changes' field='comment'>fix for log 5960</data> <data lineId='9' section='diff' field='diff'>1296a1297,1298</data> <data lineId='11' section='diff' field='diff'>if !(reportService = null)</data> <data lineId='12' section='diff' field='diff'>return true;</data> <data lineId='13' section='diff' field='diff'>return false;</data> <data lineId='14' section='changes' field='file'>HistoryWages.java</data> <data lineId='15' section='changes' field='version'>\main\spr2009_apr_dev\2</data> <data lineId='16' section='changes' field='date'>20090310.102844</data> <data lineId='17' section='changes' field='cr_number'>602118</data> <data lineId='18' section='changes' field='comment'>fix for log 6950</data> <data lineId='19' section='diff' field='diff'>1293a1294,1295</data> <data lineId='21' section='diff' field='diff'>if (reportService != null)</data> <data lineId='22' section='diff' field='diff'>return bar;</data> <data lineId='23' section='diff' field='diff'>return foo;</data> <data lineId='29' section='Section1' field='URL'>[url]\\rnd-spbuild-1\...\index.html[/url]</data> <data lineId='30' section='diff' field='diff'>1012c1024</data> <data lineId='31' section='diff' field='diff'>setMethod(row.getString('icpc_calc');</data> <data lineId='24' section='changes' field='file'>Wages.java</data> <data lineId='25' section='changes' field='date'>20080310.102844</data> <data lineId='26' section='changes' field='user'>ryanj</data> <data lineId='27' section='changes' field='cr_number'>602218</data> <data lineId='28' section='diff' field='diff'>1290a1291,1292</data> </interface-categories> <?xml version='1.0' encoding='utf-8'?> <xsl:stylesheet version='1.1' xmlns='http://www.w3.org/1999/xhtml' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'> <!-- call this stylesheet with diffs=false() to suppress the optional changeset column --> <xsl:param name='diffs' select='true()'/> <xsl:output omit-xml-declaration='no' method='xml' indent='yes' xml:space='default' encoding='utf-8'/> <xsl:template match='/'> <html xml:lang='en'> <head> <title>table example</title> <style type='text/css'>table{table-layout:fixed;width:auto}</style> </head> <body> <table width='0' summary='summary goes here for accessibility'> <caption>caption goes here for accessibility</caption> <thead> <tr> <th>Line #</th> <th>File</th> <th>Version</th> <th>Date</th> <th>User</th> <th>CR Number</th> <th>Comment</th> <xsl:if test='$diffs'><th>Changeset</th></xsl:if><!-- optional column --> </tr> </thead> <tfoot><!-- optional --> <tr> <th>Line #</th> <th>File</th> <th>Version</th> <th>Date</th> <th>User</th> <th>CR Number</th> <th>Comment</th> <xsl:if test='$diffs'><th>Changeset</th></xsl:if><!-- optional column --> </tr> </tfoot> <tbody> <!-- find and throw the delimiters between groups of data elements, i.e. the last section=diff before a section=changes --> <xsl:apply-templates select="//data[@section='diff']/following-sibling::data[@section='changes'][1 ]/preceding-sibling::data[1]"/> <!-- the data elements between delimiters (or end-of-parent) make up the contents of each table row --> </tbody> </table> </body> </html> </xsl:template> <xsl:template match='data'> <!-- catch the delimiting data elements and assign a group number based on delimiter occurrence number (position) --> <xsl:param name='i' select='position()'/> <!-- create a nodeset containing all non-section=changes data elements from here to the next delimiter (or end-of-parent), using xsl:variable *content* not @select --> <!-- if the count of the preceding delimiters is not equal to the current group number, the data element is not part of the current group --> <xsl:variable name='changeset'> <xsl:copy-of select="following-sibling::data[not(@section='changes') and count(preceding-sibling::data[@section='changes' and preceding-sibling::data[1]/@section='diff'])=$i]"/> </xsl:variable> <!-- handle all section=changes data elements from here to the next delimiter (or end-of-parent) using pull, to account for possible missing fields --> <!-- if the count of the preceding delimiters is not equal to the current group number, the data element is not part of the current group --> <tr> <th><xsl:value-of select='./@lineId+1'/></th> <td><xsl:value-of select="following-sibling::data[@field='file' and count(preceding-sibling::data[@section='diff']/following-sibling::data[@secti on='changes'][1])=$i][1]"/> </td> <td><xsl:value-of select="following-sibling::data[@field='version' and count(preceding-sibling::data[@section='diff']/following-sibling::data[@secti on='changes'][1])=$i][1]"/> </td> <td><xsl:value-of select="following-sibling::data[@field='date' and count(preceding-sibling::data[@section='diff']/following-sibling::data[@secti on='changes'][1])=$i][1]"/> </td> <td><xsl:value-of select="following-sibling::data[@field='user' and count(preceding-sibling::data[@section='diff']/following-sibling::data[@secti on='changes'][1])=$i][1]"/> </td> <td><xsl:value-of select="following-sibling::data[@field='cr_number' and count(preceding-sibling::data[@section='diff']/following-sibling::data[@secti on='changes'][1])=$i][1]"/> </td> <td><xsl:value-of select="following-sibling::data[@field='comment' and count(preceding-sibling::data[@section='diff']/following-sibling::data[@secti on='changes'][1])=$i][1]"/> </td> <!-- using dl markup for the name-value-pair semantics of line # - code, present the optional changeset column for this row, made up only of relevant @section=diffs from the source --> <!-- $changeset is a nodeset, to isolate the preceding-sibling check for @section!=diff to the current group instead of the entire source file --> <!-- the for-each @select chooses all data elements in the nodeset with @section=diff, only if their preceding-sibling axes witin the nodeset are clear of other @section values --> <xsl:if test='$diffs'> <td> <dl> <xsl:for-each select="$changeset//data[@section='diff' and not(preceding-sibling::data[@section!='diff'])]"> <dt><xsl:value-of select='./@lineId'/></dt> <dd><xsl:copy-of select='./text()'/> </dd> </xsl:for-each> </dl> </td> </xsl:if> </tr> </xsl:template> </xsl:stylesheet>
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
RE: [xsl] Mandatory and Missing Col, Wendell Piez | Thread | Re: [xsl] Create Table, Eric J. Bowman |
RE: [xsl] Mandatory and Missing Col, Shashank Jain | Date | Re: [xsl] Create Table, Eric J. Bowman |
Month |