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 August 21st, 2003, 02:36 PM
Registered User
 
Join Date: Aug 2003
Location: , , .
Posts: 5
Thanks: 0
Thanked 0 Times in 0 Posts
Default sorting and preceding-sibling

Hi All,

I have an XML structure like so:
<testNode>
         <date>12-Mar-2003</date>
</testNode>
<testNode>
         <date>18-Mar-2003</date>
</testNode>
<testNode>
         <date>12-Aug-2003</date>
</testNode>

When displaying this tree, I have to have the XML sorted first and then introduce a break everytime the month changes (year not important).

I have a code so that I am able to trim the Month part from the <date> and do a match with the preceding-sibling to introduce a blank row or not.
I do know that preceding-sibling and other axis-specifiers work on the doucment order and not the sort order.

I need a solution to get this accomplished. My idea was to use xtension functions in Xalan to accomplish this by working on the sorted node-set, but it is not working. Can anyone point me to a reference to how this can be done

Thanks a lot.
Reply With Quote
  #2 (permalink)  
Old August 22nd, 2003, 12:31 AM
Friend of Wrox
 
Join Date: Jun 2003
Location: Nor Hachin, Kotayk, Armenia.
Posts: 147
Thanks: 0
Thanked 0 Times in 0 Posts
Send a message via Yahoo to armmarti
Default

Hi,
Quote:
quote:
I have an XML structure like so:
<testNode>
        Â <date>12-Mar-2003</date>
</testNode>
<testNode>
        Â <date>18-Mar-2003</date>
</testNode>
<testNode>
        Â <date>12-Aug-2003</date>
</testNode>

When displaying this tree, I have to have the XML sorted first and then introduce a break everytime the month changes (year not important).
From this description it seems that you want to make grouping by month. Use Muenchian grouping method(I assume that the XML snippet you presented is wrapped into "doc" element):


Code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml"/>
    <xsl:key name="months" match="testNode" use="substring(date, 4, 3)"/>
    <xsl:template match="doc">
        <doc>
            <xsl:for-each select="testNode[generate-id() = generate-id(key('months', substring(date, 4, 3))[1])]">
                <xsl:sort select="substring(date, 4, 3)"/>
                <xsl:for-each select="key('months', substring(date, 4, 3))">
                    <xsl:copy-of select="."/>
                </xsl:for-each>
                <br/>
            </xsl:for-each>
        </doc>
    </xsl:template>
</xsl:stylesheet>
Regards,
Armen
Reply With Quote
  #3 (permalink)  
Old August 22nd, 2003, 11:59 AM
Registered User
 
Join Date: Aug 2003
Location: , , .
Posts: 5
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Thanks for the reply armmarti.

I think I left out one detail that might affect the result. I have to sort on the whole date ( which I can) and then introduce a break at every month change.

Can the following piece of code still work on that.

Please let me know. Your help greatly appreiciated.

Thanks.

Quote:
quote:Originally posted by armmarti
 Hi,
Quote:
quote:
I have an XML structure like so:
<testNode>
        Â <date>12-Mar-2003</date>
</testNode>
<testNode>
        Â <date>18-Mar-2003</date>
</testNode>
<testNode>
        Â <date>12-Aug-2003</date>
</testNode>

When displaying this tree, I have to have the XML sorted first and then introduce a break everytime the month changes (year not important).
From this description it seems that you want to make grouping by month. Use Muenchian grouping method(I assume that the XML snippet you presented is wrapped into "doc" element):


Code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml"/>
    <xsl:key name="months" match="testNode" use="substring(date, 4, 3)"/>
    <xsl:template match="doc">
        <doc>
            <xsl:for-each select="testNode[generate-id() = generate-id(key('months', substring(date, 4, 3))[1])]">
                <xsl:sort select="substring(date, 4, 3)"/>
                <xsl:for-each select="key('months', substring(date, 4, 3))">
                    <xsl:copy-of select="."/>
                </xsl:for-each>
                <br/>
            </xsl:for-each>
        </doc>
    </xsl:template>
</xsl:stylesheet>
Regards,
Armen
Reply With Quote
  #4 (permalink)  
Old August 23rd, 2003, 04:59 AM
Friend of Wrox
 
Join Date: Jun 2003
Location: Nor Hachin, Kotayk, Armenia.
Posts: 147
Thanks: 0
Thanked 0 Times in 0 Posts
Send a message via Yahoo to armmarti
Default

The detail you mentioned really changes about everything.
To sort the elements by date in this format ('dd-Mmm-yyyy') is not so trivial,
since if you would use xsl:sort and put the "data-type" attribute value equal to "text"(default)
then, for example, '01-Jan-2003' will be after '01-Aug-2003'. I think, first you have
to apply some template(s) to change the date format (e.g., '01-Aug-2003' -> '20030801'),
put the "transformed" elements into a variable and then you can sort the set easily(using data-type="number" of xsl:sort). Perhaps in this new circumstance it's more convenient to compare the current node's date value with the
previous node's date value, and if you find month-change, put the break.
If you still have difficulties, let me know, and we'll discuss till the final solution.

Regards,
Armen
Reply With Quote
  #5 (permalink)  
Old August 24th, 2003, 05:41 PM
Registered User
 
Join Date: Aug 2003
Location: , , .
Posts: 5
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Hi armmarti,

Thanks for your response to my queries. Your help is greatly appreiciated. I will go over again with what I have and what I am trying to acheive.

I have an XML structure like so:
<root>
<testNode>
         <date>12-Mar-2003</date>
</testNode>
<testNode>
         <date>18-Mar-2003</date>
</testNode>
<testNode>
         <date>19-Aug-2003</date>
</testNode>

<testNode>
         <date>12-Aug-2004</date>
</testNode>

<testNode>
         <date>13-Aug-2003</date>
</testNode>
</root>

The first task is to sort and display these date values. Sorting the date is not a problem. I have a template which returns 12-Sep-2003 as 20030912 and I can sort on this numeric value.

To illustrate,
<xsl:apply-templates select="testNode">
     <xsl:sort select="ds:dateSorter(date)" data-tyoe="number" and order="ascending"/>
</xsl:apply.....>
AND
<xsl:template match="testNode">
     ALL the other logic including <xsl:value-of select="date"/>
</xsl:template>

Works fine so far:
The second task is to introduce an empty row every time the month changes: so for the given XML:

12-Mar-2003
18-Mar-2003
EMPTY ROW HERE
13-Aug-2003
19-Aug-2003
12-Aug-2004

As can be seen the year change is not important. Once the XML is sorted I am intersetd in only introducing a line break at every month change.

I am using preceding-sibling on the sorted node while knowing that axis specifiers work on the document order and not the sorted one. Incredibly it works perfectly OK but with a certain exception. Dont know if that exception is relevant, but If I dont get a satisfactory explanation with this information, I will come back and post more information.

Please let me know why would this method fail certain times and also let me know of any other method that can be used.

Thanks a million.
Reply With Quote
  #6 (permalink)  
Old August 25th, 2003, 12:23 AM
Friend of Wrox
 
Join Date: Jun 2003
Location: Nor Hachin, Kotayk, Armenia.
Posts: 147
Thanks: 0
Thanked 0 Times in 0 Posts
Send a message via Yahoo to armmarti
Default

Hi,

the reason that you can't use preceding-sibling axis to achieve the goal is already stated by you: the axis works on the
XML source's internal tree-representation(the XSLT processor builds the tree before applying a stylesheet). Therefore,
when you say "xsl:sort", it just begins to process the nodes in the order you specify, sorting can't affect any axis processing. Therefore, I can suggest to make a trick ;) ...
Let's copy the sorted elements into a variable(restructure the document), then use
preceding-sibling(I'll prefer following-sibling, though there isn't a great difference):

Code:
...

        <xsl:variable name="sorted">
            <xsl:for-each select="/doc/testNode">
                <xsl:sort select="ds:dateSorter(date)" data-type="number"/>
                <xsl:copy-of select="."/>
            </xsl:for-each>
        </xsl:variable>
then you can treat all the "testNode" elements, which are in the temporary tree (kept in the variable $sorted), as siblings which are standing there in the sorted order:

Code:
...

            <xsl:for-each select="$sorted/*">
                <xsl:value-of select="date"/>
                <xsl:if test="substring(following-sibling::*[1]/date, 4, 3) != substring(date, 4, 3)">
                    <br/>
                </xsl:if>
                                <br/> 
            </xsl:for-each>
And finally you must use RTF to nodeset conversion(if you don't use Saxon, which will make the conversion implicitly if you'll
put version="1.1" in the XML declaration). About any vendor has something like EXSLT's
Code:
node-set(RTF)
function.
You just have to pass the RTF ($sorted here) to the function node-set to make the conversion explicitly:

Code:
exslt:node-set($sorted)
Regards,
Armen
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
preceding-sibling::comment() bonekrusher XSLT 11 October 1st, 2008 11:38 AM
Using preceding-sibling mcanne98 Infopath 0 September 11th, 2008 11:09 PM
preceding-sibling descendant xaun XSLT 3 February 28th, 2006 02:48 PM
preceding-sibling jonesyp XSLT 2 November 22nd, 2005 12:29 PM
preceding-sibling behaviour andrewcday XSLT 6 December 3rd, 2004 03:24 PM



All times are GMT -4. The time now is 02:22 PM.


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