Wrox Programmer Forums

Need to download code?

View our list of code downloads.

Go Back   Wrox Programmer Forums > XML > XSLT
Password Reminder
Register
| FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of tens of thousands of software programmers and website developers including Wrox book authors and readers. As a guest, you can read any forum posting. By joining today you can post your own programming questions, respond to other developers’ questions, and eliminate the ads that are displayed to guests. Registration is fast, simple and absolutely free .
DRM-free e-books 300x50
Reply
 
Thread Tools Search this Thread Display Modes
  #1 (permalink)  
Old March 26th, 2008, 10:51 AM
Registered User
 
Join Date: Mar 2008
Location: , , Canada.
Posts: 3
Thanks: 0
Thanked 0 Times in 0 Posts
Default Problems rendering to a table with sorted results

I'm working on an XML based sitemap and ran into some sorting issues so I went back to basics for testing purposes. I've created a simple test with a class student list. This code is pretty much the same as a tutorial I found a while back and I understand the logic, it's just the sort that gives me issues. If I take out the sort, it will render the names in the order they appear in the xml. With the sort it'll grab the first name, 4th name, 7th name etc and order those. So the first time going through the for-each loop it would grab Zeke, Paige, Julie, Rachel, Bart and Martin and sort them so Bart would show up first. Then when it is at Bart, it grabs the next 2 siblings which happen to be Alex and Jenny. Then it goes to Julie and the next 2 siblings and so on and so forth. Is there anyway I can have all the names sorted properly in a table? I'd like to keep the variable of cellsPerRow so I can dynamically change this at any time.

This is my xml that I'm testing with:
<ClassList>
    <Student Name="Zeke"/>
    <Student Name="Barb"/>
    <Student Name="Frank"/>
    <Student Name="Paige"/>
    <Student Name="Aaron"/>
    <Student Name="Jake"/>
    <Student Name="Julie"/>
    <Student Name="Lisa"/>
    <Student Name="Bob"/>
    <Student Name="Rachel"/>
    <Student Name="Johnny"/>
    <Student Name="Dana"/>
    <Student Name="Bart"/>
    <Student Name="Alex"/>
    <Student Name="Jenny"/>
    <Student Name="Martin"/>
</ClassList>

My xsl is:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 version="1.0">
<xsl:output method="html" indent="no"/>


<xsl:variable name="cellsPerRow" select="3"/>


<xsl:template match="/">
<html>
<head>
    <title>Class List</title>
</head>
<body>
    <table border="1" cellspacing="5" cellpadding="3" width="100px">
        <xsl:apply-templates select="ClassList"/>
    </table>
</body>
</html>
</xsl:template>


<xsl:template match="ClassList">
    <xsl:for-each select="Student[position() mod $cellsPerRow = 1]">
    <xsl:sort select="@Name" order="ascending"/>
        <tr>
        <xsl:apply-templates
            select=".|following-sibling::Student[position() &lt; $cellsPerRow]"/>
        </tr>
    </xsl:for-each>
</xsl:template>


<xsl:template match="Student">
    <td align="center">
        <xsl:value-of select="@Name"/></td>
    <xsl:if test="(position() = last()) and (position() &lt; $cellsPerRow)">
        <xsl:call-template name="FillerCells">
            <xsl:with-param name="cellCount" select="$cellsPerRow - position()"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

<xsl:template name="FillerCells">
    <xsl:param name="cellCount"/>
    <td>#160;</td>
    <xsl:if test="$cellCount > 1">
        <xsl:call-template name="FillerCells">
            <xsl:with-param name="cellCount" select="$cellCount - 1"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>
</xsl:stylesheet>

The result I get is:

Code:
<table border="1" cellspacing="5" cellpadding="3" width="100px">
    <tr>
        <td>Bart</td><td>Alex</td><td>Jenny</td>
    </tr>
    <tr>
        <td>Julie</td><td>Lisa</td><td>Bob</td>
    </tr>
    <tr>
        <td>Martin</td><td></td><td></td>
    </tr>
    <tr>
        <td>Paige</td><td>Aaron</td><td>Jake</td>
    </tr>
    <tr>
        <td>Rachel</td><td>Johnny</td><td>Dana</td>
    </tr>
    <tr>
        <td>Zeke</td><td>Barb</td><td>Frank</td>
    </tr>
</table>
Reply With Quote
  #2 (permalink)  
Old March 26th, 2008, 11:05 AM
samjudson's Avatar
Friend of Wrox
Points: 8,687, Level: 40
Points: 8,687, Level: 40 Points: 8,687, Level: 40 Points: 8,687, Level: 40
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Aug 2007
Location: Newcastle, , United Kingdom.
Posts: 2,128
Thanks: 1
Thanked 189 Times in 188 Posts
Default

It is only applying the sort after it has selected the first element for each row, so I suspect leave the work of the row selection to an <xsl:if> statement later on:

Code:
<xsl:for-each select="Student">
    <xsl:sort select="@Name" order="ascending"/>
    <xsl:if test="position() mod $cellsPerRow = 1">
      ...
    </xsl:if>
</xsl:for-each>
/- Sam Judson : Wrox Technical Editor -/
Reply With Quote
  #3 (permalink)  
Old March 26th, 2008, 12:10 PM
mhkay's Avatar
Wrox Author
Points: 18,481, Level: 59
Points: 18,481, Level: 59 Points: 18,481, Level: 59 Points: 18,481, Level: 59
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Apr 2004
Location: Reading, Berks, United Kingdom.
Posts: 4,960
Thanks: 0
Thanked 292 Times in 287 Posts
Default

You really need a two-phase approach: first sort the nodes, then group them. This is much easier in XSLT 2.0 than in 1.0. In 1.0 it can only be done with the help of the xx:node-set() extension function which is present in most processors. Alternatively use two stylesheets running in series (a mini-pipeline).

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
Reply With Quote
  #4 (permalink)  
Old March 27th, 2008, 04:31 PM
Registered User
 
Join Date: Mar 2008
Location: , , Canada.
Posts: 3
Thanks: 0
Thanked 0 Times in 0 Posts
Default

I think I've found the answer. I ran my xml through an xsl to render off a sorted xml then I took that xml and rendered it with the original xsl I was working on to get the formatting. This is the xsl for the sorting:

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output media-type="xml"/>

<xsl:template match="/child::node()">

    <xsl:text disable-output-escaping="yes">&lt;</xsl:text>
    <xsl:value-of select="local-name(current())"/>
    <xsl:text disable-output-escaping="yes">&gt;</xsl:text>
     <xsl:for-each select="child::node()">
        <xsl:sort select="@Name" order="ascending"/>
        <xsl:apply-templates select="."/>
     </xsl:for-each>

        <xsl:text disable-output-escaping="yes">&lt;</xsl:text>/<xsl:value-of select="local-name(current())"/><xsl:text disable-output-escaping="yes">&gt;</xsl:text>
</xsl:template>

<xsl:template match="@* | node()">
    <xsl:copy>
     <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
</xsl:template>
</xsl:stylesheet>


I tried to make it dynamic enough so it would be reusable but the only thing I ran into was the actual sort by. As much as I would have loved to pass in what to order it by, that didn't work with the sort. But other than that this should work with any xml once the sort by attribute is changed.
Reply With Quote
  #5 (permalink)  
Old March 27th, 2008, 04:48 PM
mhkay's Avatar
Wrox Author
Points: 18,481, Level: 59
Points: 18,481, Level: 59 Points: 18,481, Level: 59 Points: 18,481, Level: 59
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Apr 2004
Location: Reading, Berks, United Kingdom.
Posts: 4,960
Thanks: 0
Thanked 292 Times in 287 Posts
Default

No, disable-output-escaping is not the answer. It's only a way of storing up trouble for yourself later. It doesn't work in all environments (notoriously Firefox) because it depends on the transformation being immediately followed by serialization to lexical XML. It stops your code being used as input to another transformation in a pipeline, and is generally fragile.

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
Reply With Quote
  #6 (permalink)  
Old March 27th, 2008, 05:47 PM
samjudson's Avatar
Friend of Wrox
Points: 8,687, Level: 40
Points: 8,687, Level: 40 Points: 8,687, Level: 40 Points: 8,687, Level: 40
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Aug 2007
Location: Newcastle, , United Kingdom.
Posts: 2,128
Thanks: 1
Thanked 189 Times in 188 Posts
Default

The following does what you have tried to do above:

Code:
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output media-type="xml"/>

<xsl:template match="/*">
  <xsl:copy>
    <xsl:apply-templates select="*">
      <xsl:sort select="@Name" order="ascending"/>
    </xsl:apply-template>
  </xsl:copy>
</xsl:template>

<xsl:template match="@* | node()">
  <xsl:copy>
    <xsl:apply-templates select="@* | node()"/>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>
/- Sam Judson : Wrox Technical Editor -/
Reply With Quote
  #7 (permalink)  
Old March 27th, 2008, 05:54 PM
Registered User
 
Join Date: Mar 2008
Location: , , Canada.
Posts: 3
Thanks: 0
Thanked 0 Times in 0 Posts
Default

That worked perfectly thanks! I guess I should have played around with it some more to try and make it more efficient and easier to read.:)

Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
XSLT rendering problems in IE7 for Vista tripecac XSLT 17 July 4th, 2007 10:07 AM
Table rendering with table & comboBox pazzuzu Java GUI 0 May 9th, 2007 09:04 AM
Grouped and sorted table row numbers ADenny XSLT 1 April 24th, 2006 10:06 AM
ASP.NET controls & Mozilla: Rendering Problems hgberman ASP.NET 1.0 and 1.1 Basics 6 February 3rd, 2006 06:41 PM
sorted table crmpicco Javascript How-To 0 March 17th, 2005 10:29 AM



All times are GMT -4. The time now is 03:36 AM.


Powered by vBulletin®
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.
© 2013 John Wiley & Sons, Inc.