XML Editor
Sign up for a WebBoard account Sign Up Keyword Search Search More Options... Options
Chat Rooms Chat Help Help News News Log in to WebBoard Log in Not Logged in
Show tree view Topic
Topic Page 1 2 3 4 5 6 7 8 9 Go to previous topicPrev TopicGo to next topicNext Topic
Postnext
N TSubject: Sorting XSL and limiting only first n elements
Author: N T
Date: 01 Aug 2005 02:47 PM
I have an XML document that have about 200 nodes that look roughly like this:

<root>
<news>
<industry>Aerospace</industry>
<lastupdated>7/28/2005 12:01:00 AM</lastupdated>
<title>News from aerospace</title>
</news>
<news>
<industry>Mechanical</industry>
<lastupdated>6/28/2004 12:01:00 AM</lastupdated>
<title>News from mechanical</title>
</news>
<news>
<industry>Aerospace</industry>
<lastupdated>4/2/2002 12:01:00 PM</lastupdated>
<title>News from aerospace</title>
</news>
<news>
<industry>Electrical</industry>
<lastupdated>3/8/2005 12:01:00 AM</lastupdated>
<title>News from electrical</title>
</news>
<news>
<industry>Computer Science</industry>
<lastupdated>3/28/2002 12:01:00 AM</lastupdated>
<title>News from CS</title>
</news>
<news>
<industry>Aerospace</industry>
<lastupdated>4/28/2005 12:01:00 AM</lastupdated>
<title>News from aerospace</title>
</news>
</root>


I need to sort these nodes where industry is Aerospace or Electrical (for example), sort them by lastupdated (reverse chronological). I am able to do that so far successfully. Its just that I need to display the top 2 items (of the 3 or more that are selected). How do I accomplish that? I cannot use the position(), because it relates to the nodes in the document, not the position of nodes after sort.

Here is the XSL:

<xsl:template match="/">
<xsl:for-each select="root/news">
<!-- lastupdated is MM/DD/YYYY HH:MI:SS XM e.g. 7/27/2005 4:12:22 PM -->
<xsl:sort order="descending" data-type="number" select='substring-after(substring-after(substring-before(LASTUPDATED, " "), "/"), "/")'></xsl:sort>
<!-- sort the yyyy as number -->
<xsl:sort order="descending" data-type="number" select='substring-before(substring-before(LASTUPDATED, " "), "/")'></xsl:sort>
<!-- sort MM as number -->
<xsl:sort order="descending" data-type="number" select='substring-after(substring-before(LASTUPDATED, " "), "/")'></xsl:sort>
<!-- sort date as number -->
<xsl:sort order="descending" select='substring-after(substring-after(LASTUPDATED, " "), " ")'></xsl:sort>
<!-- within day, sort XM (AM/PM) as string, PM first -->
<xsl:sort order="descending" data-type="number" select='substring-before(substring-after(LASTUPDATED, " "), ":")'></xsl:sort>
<!-- sort the HH as number -->
<xsl:sort order="descending" data-type="number" select='substring-before(substring-after(substring-after(LASTUPDATED, " "), ":"), ":")'></xsl:sort>
<!-- sort the MM as number -->
<!-- The one problem currently with this approach is that 12:20 AM will be considered latest when compared to 9:20 AM -->

<xsl:if test="industry/text() = 'Aerospace' or
industry/text() = 'Electrical'
">
<!-- <xsl:if test="position() &lt; 2"> -->

<tr><td>


||<xsl:value-of select='concat(substring-before(substring-after(LASTUPDATED, " "), ":"), ":", substring-before(substring-after(substring-after(LASTUPDATED, " "), ":"), ":"), " ", substring-after(substring-after(LASTUPDATED, " "), " "), " ET, ", substring-before(LASTUPDATED, " "))' />
</td></tr>

<tr><td>
<xsl:value-of select="title"/>
</td></tr>
<!-- </xsl:if> -->
</xsl:if>

</xsl:for-each>
</xsl:template>

Postnext
(Deleted User) Subject: Sorting XSL and limiting only first n elements
Author: (Deleted User)
Date: 01 Aug 2005 03:36 PM
You can use position() which is relative to the context nodeset.

Hope this help.
Song.

Postnext
N TSubject: Sorting XSL and limiting only first n elements
Author: N T
Date: 01 Aug 2005 03:44 PM
Thanks for your reply. However, I tried that and did not work for me. The positions that are returned are 1,3,4,5 (because thats the position of original node-set). I tried:
<!-- <xsl:if test="position() &lt; 2"> -->

But, it only got me 1 element in result. because position() returned 1, 3, 4, 5.

Am I doing something wrong? Please help.

Postnext
(Deleted User) Subject: Sorting XSL and limiting only first n elements
Author: (Deleted User)
Date: 01 Aug 2005 05:02 PM
give your sorting criteria, the first item is Aerospace, the second is Mechanical, third is Aerospace again... so your xsl:if to filter out Aerospace and Electrical will have the nodes with positions as 1, 3...

please be more specific about what you mean by 'top 2 items'. do you want to show the top 2 in the entire nodeset, or top2 for both Aerospace and Electrical?

song.

Postnext
N TSubject: Sorting XSL and limiting only first n elements
Author: N T
Date: 01 Aug 2005 05:07 PM
Hello. I need to basically display top 2 items in reverse chronological order that have either Aerospace or Electrical as industry (the filter basically gives me 4 items, 3 with Aerospace and 1 with Electrical). I need the first 2 (assuming they are sorted by lastupdated).

Thanks a lot. Please feel free to send me any question/comment. I am a newbie in XSL and am not sure if I am proceeding in the right direction.

Postnext
(Deleted User) Subject: Sorting XSL and limiting only first n elements
Author: (Deleted User)
Date: 02 Aug 2005 09:32 AM
Given your description, you should remove the
<xsl:if test="industry/text() = 'Aerospace' or industry/text() 'Electrical' "> as a filter and put the filter in your xsl:for-each xpath predicate as:
<xsl:for-each select="root/news[industry = 'Aerospace' or industry = 'Electrical']">

And remember to activate your position() checking to make sure you only get the first two items.

You should be all set after this change.

Hope this helps.

Song.

Postnext
N TSubject: Sorting XSL and limiting only first n elements
Author: N T
Date: 02 Aug 2005 11:03 AM
Thanks a lot Song. That worked fine.

I just had 2 follow-up questions:

1) Is there a way I can make it faster (I read somewhere that I could use keys, just don't know how to?)
2) Also, in my sorting by lastupdated, I have an error, where 12:01 AM is being displayed ahead of 9:20 AM (in reverse chronological order), which is incorrect. I am sorting YYYY first (as number), then MM (as number), date (as number), AM/PM (as string descending), HH (as number), MI (as number). Is there a way to correct that?

Thanks.

Postnext
(Deleted User) Subject: Sorting XSL and limiting only first n elements
Author: (Deleted User)
Date: 02 Aug 2005 11:47 AM
xsl:key is an advanced feature in xslt. I encourage you to explore the topic yourself to get some good understanding.

as for your time sorting issue, because you sort the HH in number format with descending order, of course 12 will be ahead of 9 which put you 12:01am ahead 9:01am. change the descending to ascending should work as you expected.

song.

Posttop
(Deleted User) Subject: Sorting XSL and limiting only first n elements
Author: (Deleted User)
Date: 02 Aug 2005 11:43 AM
Given your description, you should remove the
<xsl:if test="industry/text() = 'Aerospace' or industry/text() 'Electrical' "> as a filter and put the filter in your xsl:for-each xpath predicate as:
<xsl:for-each select="root/news[industry = 'Aerospace' or industry = 'Electrical']">

And remember to activate your position() checking to make sure you only get the first two items.

You should be all set after this change.

Hope this helps.

Song.

 
Topic Page 1 2 3 4 5 6 7 8 9 Go to previous topicPrev TopicGo to next topicNext Topic
Download A Free Trial of Stylus Studio 6 XML Professional Edition Today! Powered by Stylus Studio, the world's leading XML IDE for XML, XSLT, XQuery, XML Schema, DTD, XPath, WSDL, XHTML, SQL/XML, and XML Mapping!  
go

Log In Options

Site Map | Privacy Policy | Terms of Use | Trademarks
Stylus Scoop XML Newsletter:
W3C Member
Stylus Studio® and DataDirect XQuery ™are from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2016 All Rights Reserved.