Guest David Shepheard Posted June 30, 2009 Share Posted June 30, 2009 Hi guys,XML structure: search-results object1 object2 object3 items file-item name description genre file-item name description genre file-item name description genre xslt: <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:output method="html" encoding="utf-8" omit-xml-declaration="yes"/><xsl:template match="/"><table border="0" id="research" class="style1"> <tr> <th scope="col">A</th> <th scope="col">B</th> <th scope="col">C</th> </tr> <xsl:for-each select="search-results/items/file-item"> <tr> <td><xsl:if test="genre = 'A'"><xsl:value-of select="name"/></xsl:if></td> <td><xsl:if test="contains(genre, 'B')"><xsl:value-of select="name"/></xsl:if></td> <td><xsl:if test="genre = 'C'"><xsl:value-of select="name"/></xsl:if></td> </tr> </xsl:for-each></table></xsl:template></xsl:stylesheet> My problem is, that if the first file-item has a genre of "a", its puts it column "a", but then if the next file-item has a genre of "b" (allthough it puts it in the "b" column) it puts it on the next row.The table im getting looks somthing like this:A-----B------Caa-------b-------ba--------------cbut i want it to look like this:A B Ca b ca b cetc...Any help would be much appreciated!! Link to comment Share on other sites More sharing options...
boen_robot Posted July 2, 2009 Share Posted July 2, 2009 That's a very interesting issue you have...I can't think of a single transformation that can do it. Consider having two transformations instead: one to turn your XML into one where each genre is grouped under it's own node, and another where each row is composed by taking each node in that intermediate XML.The intermediate XML should look something like: <file-items> <genre> <item> <name></name> <description></description> </item> <!-- More item elements from this genre --> </genre> <!-- More "genre" elements for each genre --></file-items> from this XML, generating the table should be relatively easy: <xsl:template match="/"> <table border="0" id="research" class="style1"> <tr> <th scope="col">A</th> <th scope="col">B</th> <th scope="col">C</th> </tr> <xsl:for-each select="file-items/genre[1]/item"> <xsl:variable name="pos" select="position()" /> <tr> <td><xsl:value-of select="name"/></td> <td><xsl:value-of select="../genre[2]/item[number($pos)]/name"/></td> <td><xsl:value-of select="../genre[3]/item[number($pos)]/name"/></td> </tr> </xsl:for-each> </table></xsl:template> Actually getting that intermediate XML is going to be the harder part. Perhaps something like: <xsl:template match="/"> <file-items> <genre><xsl:apply-templates select="search-results/items/file-item[genre='A']" /></genre> <genre><xsl:apply-templates select="search-results/items/file-item[genre='B']" /></genre> <genre><xsl:apply-templates select="search-results/items/file-item[genre='C']" /></genre> </file-items></xsl:template><xsl:template match="*"><xsl:copy><xsl:apply-templates/></xsl:copy></xsl:template><xsl:template match="file-item"><item><xsl:apply-templates match="*[local-name() != 'genre']" /></item></xsl:template> Link to comment Share on other sites More sharing options...
aalbetski Posted July 21, 2009 Share Posted July 21, 2009 This may work for you, It does not require an intermediate step. It automatically determines the largest number of any one item and builds a corresponding table. It does rely on the MSXML node-set function and it is hard coded for three genres. These could be revised and streamlined if needed, but maybe this can get you started. Sample XML <table> <genre>C</genre> <genre>B</genre> <genre>A</genre> <genre>A</genre> <genre>A</genre> <genre>B</genre> <genre>C</genre> <genre>A</genre> <genre>B</genre> <genre>B</genre> <genre>B</genre> <genre>B</genre> </table> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" version="1.0"> <xsl:output method="html" /> <xsl:template match="/"> <xsl:variable name="GenreCount"> <top> <count> <xsl:value-of select="count(//genre[text()='A'])" /> </count> <count> <xsl:value-of select="count(//genre[text()='B'])" /> </count> <count> <xsl:value-of select="count(//genre[text()='C'])" /> </count> </top> </xsl:variable> <xsl:variable name="IndexCount"> <xsl:for-each select="msxsl:node-set($GenreCount)//count"> <xsl:sort select="text()" order="descending"/> <xsl:if test="position()=1"> <xsl:value-of select="text()"/> </xsl:if> </xsl:for-each>. </xsl:variable> <table border="1"> <xsl:call-template name="DoRow"> <xsl:with-param name="IndexCount" select="$IndexCount"/> </xsl:call-template> </table> </xsl:template> <xsl:template name="DoRow"> <xsl:param name="IndexCount"/> <xsl:param name="index" select="1"/> <tr> <td><xsl:value-of select="//genre[text()='A'][$index]/text()"/></td> <td><xsl:value-of select="//genre[text()='B'][$index]/text()"/></td> <td><xsl:value-of select="//genre[text()='C'][$index]/text()"/></td> </tr> <xsl:if test="$index < $IndexCount" > <xsl:call-template name="DoRow"> <xsl:with-param name="IndexCount" select="$IndexCount"/> <xsl:with-param name="index" select="$index + 1"/> </xsl:call-template> </xsl:if> </xsl:template> produces:A B C A B C A B - A B - - B - - B -(- added as placeholder, will not appear in output) Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.