Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
| 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 software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
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.
 
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
 
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
 
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
 
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.
 
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




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





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.