CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 7 of 7

Thread: XSL sorting

  1. #1
    Join Date
    May 2004
    Posts
    7

    XSL sorting

    Hi
    I have an xml file which is transformed using xsl and displayed in HTML. I am using msxml3 and IE6, with this namespace <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

    My problem is sorting.

    The xsl sorts the xml using values it gets from some form fields in the HTML page. The field it gets values from is called SortVal, and its value is created dynamically from a Lotus Notes document form.

    SortVal contains the value to sort the xml by. In the HTML file I set the value of a <xslaram> to be the SortVal. I then use this param to determine what to sort by.

    here is my xml
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <?xml-stylesheet type="text/xsl" href="test11.xsl"?>
    <viewentries toplevelentries="5" error="0">
    <headerdata>
    <State>ACT</State>
    <CaseNo>CN1</CaseNo>
    <From/>
    <To/>
    <SortBy>1</SortBy>
    <SelectBy>All</SelectBy>
    <srt>EntryNo</srt>
    </headerdata>
    <Case>
    <CaseNo>CN1</CaseNo>
    <SubName>Homer J Simpson</SubName>
    <CaseMgr/>
    <RefType>Pin</RefType>
    <RefVal>000000000</RefVal>
    <CaseOff>Myee Riri</CaseOff>
    <OpName/>
    <Entries>5</Entries>
    </Case>
    <viewentry position="1" noteid="docnoteid1">
    <DateVal>01/02/2005</DateVal>
    <TimeVal>55555</TimeVal>
    <EntryNo>10</EntryNo>
    <Comments>I gots something to tell ya</Comments>
    <EnterBy>ANAME</EnterBy>
    <EnterDate>08/05/2003</EnterDate>
    <Action/>
    <RowNo>1</RowNo>
    </viewentry>
    <viewentry position="2" noteid="docnoteid1">
    <DateVal>27/02/2001</DateVal>
    <TimeVal>44444</TimeVal>
    <EntryNo>1</EntryNo>
    <Comments>Test Comment</Comments>
    <EnterBy>DNAME</EnterBy>
    <EnterDate>08/05/2003</EnterDate>
    <Action/>
    <RowNo>2</RowNo>
    </viewentry>
    <viewentry position="3" noteid="docnoteid1">
    <DateVal>31/12/2004</DateVal>
    <TimeVal>11111</TimeVal>
    <EntryNo>3</EntryNo>
    <Comments>I gots something to tell ya</Comments>
    <EnterBy>FNAME</EnterBy>
    <EnterDate>08/05/2003</EnterDate>
    <Action/>
    <RowNo>4</RowNo>
    </viewentry>
    <viewentry position="4" noteid="docnoteid1">
    <DateVal>15/09/2003</DateVal>
    <TimeVal>cff</TimeVal>
    <EntryNo>4</EntryNo>
    <Comments>Some comments about somthing</Comments>
    <EnterBy>ZNAME</EnterBy>
    <EnterDate>04/05/2003</EnterDate>
    <Action>Further action required goes here</Action>
    <RowNo>2</RowNo>
    </viewentry>
    <viewentry position="5" noteid="docnoteid1">
    <DateVal>28/11/2002</DateVal>
    <TimeVal>33333</TimeVal>
    <EntryNo>15</EntryNo>
    <Comments>I gots something to tell ya</Comments>
    <EnterBy>QNAMEa</EnterBy>
    <EnterDate>08/05/2003</EnterDate>
    <Action/>
    <RowNo>1</RowNo>
    </viewentry>
    </viewentries>


    here is my xsl
    <?xml version="1.0"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xslaram name="sortby">DateVal</xslaram>
    <xslaram name="datatype">number</xslaram>
    <xsl:template match="/">
    <xsl:apply-templates select="viewentries/headerdata"/>
    <table class="maintable">
    <tr>
    <td>
    <br/>
    <xsl:apply-templates select="viewentries/Case"/>
    <xsl:apply-templates select="viewentries/viewentry"/>
    </td>
    </tr>
    </table>
    <p>------ End of Report ------</p>
    </xsl:template>
    <xsl:template match="viewentries/headerdata">
    <p>PRDESKTOP<br/>
    <xsl:value-of select="State"/>
    <xsl:value-of select="CaseNo"/>
    <xsl:if test="From/text()">
    From:<xsl:value-of select="From"/> To:<xsl:value-of select="To"/>
    </xsl:if>
    <br/>
    Sorted by:<xsl:value-of select="SortBy"/> Select Option:<xsl:value-of select="SelectBy"/>
    <br/>
    <br/>
    RUNNING SHEET REPORT</p>
    </xsl:template>
    <xsl:template match="viewentries/Case">
    <div class="category">
    <table class="standard" cellspacing="0" cellpadding="0">
    <tr class="title">
    <td class="titlecell" width="108">Case Number</td>
    <td width="450">Subject Name</td>
    </tr>
    <tr class="content">
    <td width="108">
    <xsl:value-of select="CaseNo"/>
    </td>
    <td width="450">
    <xsl:value-of select="SubName"/>
    </td>
    </tr>
    </table>
    <BR/>
    <table class="standard" cellspacing="0" cellpadding="0">
    <tr class="title">
    <td class="titlecell" width="225"> Case Manager</td>
    <td class="titlecell" width="180">Reference Type</td>
    <td class="titlecell" width="135">Reference</td>
    </tr>
    <tr class="content">
    <td class="titlecell" width="225">
    <xsl:value-of select="CaseMgr"/>
    </td>
    <td class="titlecell" width="180">
    <xsl:value-of select="RefType"/>
    </td>
    <td class="titlecell" width="135">
    <xsl:value-of select="RefVal"/>
    </td>
    </tr>
    </table>
    <BR/>
    <table class="standard" cellspacing="0" cellpadding="0">
    <tr class="title">
    <td class="titlecell" width="225">Case Officer</td>
    <td class="titlecell" width="270">Operation Name</td>
    <td class="titlecell" width="36"> </td>
    <td class="titlecell" width="54">Entries</td>
    </tr>
    <tr class="content">
    <td class="contentcell" width="225">
    <xsl:value-of select="CaseOff"/>
    </td>
    <td class="contentcell" width="270">
    <xsl:value-of select="OpName"/>
    </td>
    <td class="contentcell" width="36"/>
    <td class="contentcell" width="54">
    <xsl:value-of select="Entries"/>
    </td>
    </tr>
    </table>
    <BR/>
    </div>
    <hr width="658" align="left"/>
    </xsl:template>
    <xsl:template match="viewentries/viewentry">
    <div class="child" id="Sheet Entry">
    <table class="standard" cellspacing="0" cellpadding="0">
    <xsl:if test="$sortby='DateVal'">
    <xsl:value-of select="$sortby" />
    <xsl:for-each select="/viewentries/viewentry">
    <xsl:for-each select="DateVal">
    <xsl:sort select="substring(. , 7,2)" order="ascending" data-type="number"/>
    <xsl:sort select="substring(. , 4,2)" order="ascending" data-type="number"/>
    <xsl:sort select="substring(. , 1,2)" order="ascending" data-type="number"/>
    <xsl:value-of select="."/>
    </xsl:for-each>
    </xsl:for-each>
    </xsl:if>
    <xsl:if test="$sortby='EnterBy' ">
    <xsl:value-of select="$sortby" />
    <xsl:for-each select="/viewentries/viewentry">
    <xsl:sort select="$sortby" data-type="text" />
    </xsl:for-each>
    </xsl:if>
    <xsl:if test="$sortby='EntryNo'">
    <xsl:value-of select="$sortby" />
    <xsl:for-each select="/viewentries/viewentry">
    <xsl:sort select="$sortby" data-type="number" />
    </xsl:for-each>
    </xsl:if>
    <xsl:choose>
    <xsl:when test="RowNo/text()">
    <tr class="comments">
    <td width="658" colspan="3">
    <hr width="658" align="left" valign="bottom"/>
    </td>
    </tr>

    </xsl:when>
    <xsltherwise>
    <tr class="comments">
    <td width="658" colspan="3">
    <hr width="90" align="left" valign="bottom"/>
    </td>
    </tr>
    </xsltherwise>
    </xsl:choose>

    <tr class="title">
    <td width="90">Date</td>
    <td width="396" class="commentstitle">Comments</td>
    <td width="153">Entered By</td>
    </tr>
    <tr class="content">
    <td width="90">
    <xsl:value-of select="DateVal"/>
    </td>
    <td width="396" rowspan="5" valign="top" class="comments">
    <xsl:value-of select="Comments"/>
    </td>
    <td width="153">
    <xsl:value-of select="EnterBy"/>
    </td>
    </tr>
    <tr class="title">
    <td width="90">Time</td>
    <td width="153">Entered Date</td>
    </tr>
    <tr class="content">
    <td width="90">
    <xsl:value-of select="TimeVal"/>
    </td>
    <td width="153">
    <xsl:value-of select="EnterDate"/>
    </td>
    </tr>
    <tr class="title">
    <td width="90">Entry No</td>
    <td width="153">Action Req.</td>
    </tr>
    <tr class="content">
    <td width="90">
    <xsl:value-of select="EntryNo"/>
    </td>
    <td width="153">
    <xsl:value-of select="Action"/>
    </td>
    </tr>
    </table>
    <br/>
    </div>
    <!-- </xsl:for-each> -->
    </xsl:template>
    </xsl:stylesheet>

    I am not sure about the date sorting yet but the other sorting (ENntryNo and EnterBy) do not work either.

    My javascript correctly changes the value of the sortby param. Everthing turns out properly, only it is not sorted. I am especially having problems with sorting by dtae (since there is no sort by date function)

    Any ideas

  2. #2
    Join Date
    May 2003
    Location
    Denmark
    Posts
    1,315
    Your first sort fails because there is only ever one DateVal selected when the sort is invoked so nothing is sorted. IE first you sort the first elements dateval with it self, and prints that, then you sort the second elements dateval with itself and prints that, and so on.

    You need to do something like this

    Code:
    <xsl:value-of select="$sortby"/>
    <xsl:for-each select="/viewentries/viewentry">
      <xsl:sort select="number(substring(DateVal/text(),7,4))" data-type="number" order="ascending"/>
      <xsl:sort select="number(substring(DateVal/text(),4,2))" data-type="number" order="ascending"/>
      <xsl:sort select="number(substring(DateVal/text(),1,2))" data-type="number" order="ascending"/>
      <xsl:for-each select="DateVal">
        <xsl:value-of select="text()"/> 
      </xsl:for-each>
    </xsl:for-each>
    The inner foreach is kind of pointless.

    The other sort's fails because you can't write
    Code:
    <xsl:sort select="$sortby" data-type="number"  />
    Well OK you can, but it won't do what I think you want.
    The sort evaluates the select expression for each element selected in the for-each. $sortby will evalueate to the same string ('EntryNo' for example) for all the elements. To get the sort to sort by EntryNo you have to write
    Code:
    <xsl:sort select="EntryNo" data-type="number"/>
    Last edited by khp; May 6th, 2004 at 10:29 PM.
    The biggest problem encountered while trying to design a system that was completely foolproof,
    was, that people tended to underestimate the ingenuity of complete fools.
    Douglas Adams

  3. #3
    Join Date
    May 2004
    Posts
    7

    thanks

    thanks for the heads up about the smiley thing. Sorry I didn't notice.

    I don't think I made my point clear, or I am not understanding what you have said. I want it to sort by the same thing each time, i.e. f $sortby = EntryNo I want it to sort all by EntryNo.

    So I determine the value of $sortby and want all each <viewentry> to be sorted according to $sortby.

    The problem is it isn't sorting at all.

    Sorry if I am not making sense, I only learnt XML/XSLT/XPath 2 days ago, so I don't really know much yet.

    Thanks for the reply

  4. #4
    Join Date
    May 2003
    Location
    Denmark
    Posts
    1,315
    The problem is it isn't sorting at all.
    Yes, the problem is that, there are quite a few problems with your code. I was just addressing the problems with the sort expression. But to get evrything sorted you also have to do it in the right scope, you are putting your sort expressions in for each loops inside the the elements you want to sort. This is no good. Getting your code to work would be a major rewrite, I'am sorry but I don't have time for that right now.

    Sorry if I am not making sense, I only learnt XML/XSLT/XPath 2 days ago, so I don't really know much yet.
    I might suggest that you start working with some smaller examples. Much of your trouble here is that there are so many problems in your code, it's difficult to make any sense of it.
    The biggest problem encountered while trying to design a system that was completely foolproof,
    was, that people tended to underestimate the ingenuity of complete fools.
    Douglas Adams

  5. #5
    Join Date
    May 2004
    Posts
    7
    I'd like to start on smaller examples but unfortunately I don't have that option.

    I have to do this for work, and like my sort is out scope, xsl/xml/xpath is so out of my scope. My job requires me to program in Domino, but this is a webpage created by a Domino document.

    And I can't rewrite the code either because that would affect too many other areas as there are Domino agents, documents and forms involved in creating the xml.

    I am not the authour of the xml or xsl file. All I have done is change the namespace (it was still using wd xsl) and messed around with the sorting.

    The old one never sorted correclt either, and users complained so I have to fix it.

    So I shall have to figure this out but thanks anyway

  6. #6
    Join Date
    May 2003
    Location
    Denmark
    Posts
    1,315
    OK I'll do some of your work for you, in an effort to make the problem and solution more clear.

    If we reduce the stylesheet to the bare core of the problem. It could look something like this

    Code:
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
      <xsl:template match="/">
        <xsl:apply-templates select="viewEntries/viewentry"/>
      </xsl:template>
    
      <xsl:template match="viewentries/viewentry">
          <xsl:if test="$sortby='EntryNo'">
             <xsl:for-each select="/viewentries/viewentry">
               <xsl:sort select="$sortby" data-type="number" />
            </xsl:for-each>
         </xsl:if>
         <!-- Element content outputted here-->
      </xsl:template>
    </xsl:stylesheet>
    This fails for several reasons one of which I explained in my first post.
    The other reason is that the first template select all the viewentry elements, to be outputted in document order, but does nothing to sort the element. The elements have to be sorted when they are selected, it too late to do it, in the template that prints them.

    So to make the code work properly it has to be changed to something like


    Code:
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
      <xsl:template match="/">
         <xsl:if test="$sortby='EntryNo'">
           <xsl:apply-templates select="viewentries/viewentry">
               <xsl:sort select="EntryNo" data-type="number"/>
            </xsl:apply-templates>
         </xsl:if>
      </xsl:template>
    
      <xsl:template match="viewentries/viewentry">
         <!-- Element content outputted here-->
      </xsl:template>
    </xsl:stylesheet>
    Last edited by khp; May 7th, 2004 at 07:29 PM.
    The biggest problem encountered while trying to design a system that was completely foolproof,
    was, that people tended to underestimate the ingenuity of complete fools.
    Douglas Adams

  7. #7
    Join Date
    May 2004
    Posts
    7

    Thanks but I have a solution

    Thankyou for still bothering with me. I probably should have posted that I had a solution, I just figured from your last reply you wouldn't bother with my problem again, sorry.

    <xsl:template match="viewentries/viewentry">
    <div class="child" id="Sheet Entry">
    <table class="standard" cellspacing="0" cellpadding="0">
    <xsl:choose>
    <xsl:when test="$sortby = 'DateVal'">
    <xsl:apply-templates select="viewentry">
    <xsl:sort select="substring(DateVal, 7, 4)" />
    <xsl:sort select="substring(DateVal, 4, 2)" />
    <xsl:sort select="substring(DateVal, 1, 2)" />
    </xsl:apply-templates>
    </xsl:when>
    <xsl:otherwise>
    <xsl:apply-templates select="viewentry">
    <xsl:sort select="*[name() = $sortby]" datatype="{$datatype}" />
    </xsl:apply-templates>
    </xsl:otherwise>
    </xsl:choose>

    the xsl:params were changed to

    <xsl:param name="sortby" select="'DateVal'" />
    <xsl:param name="datatype" select="'number'" />

    now I have other problems. My xpath in my js is not working
    sortColumn = style.selectSingleNode("*//xsl:param[@name='sortby']");

    And the one to the datatype isn't either (though once I figure one out I should be all good).

    I think I have to put
    sortColumn = style.selectSingleNode("*//xsl:param[@name='sortby']").Value;

    or

    sortColumn = style.selectSingleNode("*//xsl:param[@name='sortby' @select='DateVal']");

    and I have to figure out how to set it.

    Then I have the additional problem of none of the other templates showing up.

    All this is fixable though. Just have to use the old brain.

    I got a lot of help from the xsl mailing list.

    Thanks again

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured