Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
|
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 July 6th, 2009, 04:04 PM
Authorized User
 
Join Date: Jul 2009
Posts: 25
Thanks: 1
Thanked 0 Times in 0 Posts
Default sorting nodes

Hi all,

Please help me in figuring out how to code for this xml transformation
Thwe final outcome of the xml should contain all employee with highest salary from different TypeCde (Taking into Consideration all Employees nodes)
Please let me know if u have any questions

Below is the XML i have to transform:
<Company>
<Employees>
<employee >
<TypeCde>FN</TypeCde>
<salary>100000</salary>
</employee>
<employee>
<TypeCde>CL</TypeCde>
<salary>95000</salary>
</employee>
</Employees>
<Employees>
<employee>
<TypeCde>UH</TypeCde>
<salary>89000</salary>
</employee>
<employee>
<TypeCde>FN</TypeCde>
<salary>97000</salary>
</employee>
</Employees>
<Company>
Below is the xml i need after transformation


<Company>
<Employees>
<employee >
<TypeCde>FN</TypeCde>
<salary>100000</salary>
</employee>
<employee>
<TypeCde>CL</TypeCde>
<salary>95000</salary>
</employee>
<employee>
<TypeCde>UH</TypeCde>
<salary>89000</salary>
</employee>
</Employees>
</Comapny>


Thanks

Last edited by scubin; July 6th, 2009 at 04:09 PM..
 
Old July 6th, 2009, 04:31 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

First you have to group by typeCode - the way you do that depends greatly on whether it's XSLT 2.0 or 1.0. Then sort each group and take the first in descending order.

Code:
<xsl:for-each-group select="//employee" group-by="typeCode">
  <xsl:for-each select="current-group()">
     <xsl:sort select="xs:integer(salary)" order="descending"/>
     <xsl:if test="position() = 1">
        <xsl:copy-of select="."/>
     </xsl:if>
  </xsl:for-each>
</xsl:for-each-group>
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
 
Old July 6th, 2009, 04:53 PM
Authorized User
 
Join Date: Jul 2009
Posts: 25
Thanks: 1
Thanked 0 Times in 0 Posts
Default

I want it for XSLT version 1.0 ,seems <xsl:for-each group> is for version 2.0

can i know how to group by using version 1.o

Thanks fro quick reply
 
Old July 6th, 2009, 05:52 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Search for "Muenchian Grouping" in the index to your favourite XSLT textbook.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
 
Old July 7th, 2009, 01:32 AM
Authorized User
 
Join Date: Jul 2009
Posts: 25
Thanks: 1
Thanked 0 Times in 0 Posts
Default

Thank you Michael that helped a lot and i was able to get result what i want but there is one more thing that troubling me ,in the below XML if i want Employee Id to be outputted along with
Input XML:
<Company>
<Employees>
<Id>123</Id>
<employee >
<TypeCde>FN</TypeCde>
<salary>100000</salary>
</employee>
<employee>
<TypeCde>CL</TypeCde>
<salary>95000</salary>
</employee>
</Employees>
<Employees>
<Id>234</Id>
<employee>
<TypeCde>UH</TypeCde>
<salary>89000</salary>
</employee>
<employee>
<TypeCde>FN</TypeCde>
<salary>10000</salary>
</employee>
</Employees>
<Company>
Below is the my output should be

<Company>
<Employees>
<employee >
<TypeCde>FN</TypeCde>
<salary>100000</salary>
<Id>123</Id>
<Id>234</Id>
</employee>
<employee>
<TypeCde>CL</TypeCde>
<salary>95000</salary>
<Id>123</Id>
</employee>
<employee>
<TypeCde>UH</TypeCde>
<salary>89000</salary>
<Id>234</Id>
</employee>
</Employees>
</Comapny>

based on my muenchian method below is my code snippet
<xsl:for-each select="//employee[generate-id(.) = generate-id(key('k',
TypeCde)[1])]">
<xsl:for-each select="key('k', TypeCde)">
<xsl:sort select="salary" data-type="number" order="descending"/>
<xsl:if test="position() = 1">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
what can i do to get the <Id> of Employees in output xml?


Thnaks in advance
 
Old July 7th, 2009, 03:40 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Just replace the copy-of with an apply-templates select=".", and write a template rule for Employee something like

Code:
<xsl:template match="employee">
  <xsl:copy>
    <xsl:copy-of select="*"/>
    <xsl:copy-of select="../Id"/>
  </xsl:copy>
</xsl:template>
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
 
Old July 7th, 2009, 07:49 AM
Authorized User
 
Join Date: Jul 2009
Posts: 25
Thanks: 1
Thanked 0 Times in 0 Posts
Default

Thank you very much michael for your reply but what i want is I need even the Emplotees Ids those having same salary in input XML also to be printed.The above code simply gives the first one that is having highest salary.If there are 2 or 3 Employee Ids having same highest salary I need those Employee Ids as well. Something like below .Can you tell me how to accomplish this
<Company>
<Employees>
<employee >
<TypeCde>FN</TypeCde>
<salary>1000</salary>
<Id>123</Id>
<Id>234</Id>
</employee>
<employee>
<TypeCde>CL</TypeCde>
<salary>95000</salary>
<Id>123</Id>
</employee>
<employee>
<TypeCde>UH</TypeCde>
<salary>89000</salary>
<Id>234</Id>
</employee>
</Employees>
</Comapny>

Thans a lot for your support
 
Old July 7th, 2009, 07:57 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Then you need to do a second level of grouping (group by salary) before you sort these groups on salary and choose the first; you then print the Ids for all the employees in the group.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
 
Old July 7th, 2009, 11:11 AM
Authorized User
 
Join Date: Jul 2009
Posts: 25
Thanks: 1
Thanked 0 Times in 0 Posts
Default

Iam sorry michael ,I couldnt figure out how to do that second level grouping

on salary,Iam getting lot of duplicates if iam doing 2 level grouping.Can you

help on this please

Thanks
 
Old July 8th, 2009, 01:19 AM
Friend of Wrox
 
Join Date: Jun 2008
Posts: 291
Thanks: 9
Thanked 29 Times in 29 Posts
Thumbs up

Try this:

Code:
<xsl:key name="k" match="employee" use="TypeCde"/>

<xsl:template match="Company">
<xsl:copy>
<Employees>
<xsl:for-each select="//employee[generate-id(.) = generate-id(key('k',TypeCde)[1])]">
<xsl:for-each select="key('k', TypeCde)">
<xsl:sort select="salary" data-type="number" order="descending"/>
<xsl:if test="position() = 1">
<xsl:copy>
<xsl:variable name="type" select="TypeCde"></xsl:variable>
<xsl:variable name="sal" select="salary"></xsl:variable>
<xsl:copy-of select="$type"/>
<xsl:copy-of select="$sal"/>
<xsl:copy-of select="../Id"/>
<xsl:copy-of select="../..//Id[..//TypeCde = $type][not(..//salary = $sal)]"/>
</xsl:copy>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</Employees>
</xsl:copy>
</xsl:template>


There may be better solution from experts.
__________________
Rummy





Similar Threads
Thread Thread Starter Forum Replies Last Post
Adding and Sorting nodes georgemeng XSLT 4 December 1st, 2008 12:13 PM
Sorting some nodes by attribute value acw274 XSLT 8 July 2nd, 2008 01:22 AM
How to value in b/n nodes Swetha XSLT 1 May 20th, 2008 12:20 PM
Datagrid sorting by non alphabetical sorting? LLAndy VS.NET 2002/2003 1 July 15th, 2004 01:20 AM
HELP! More complicate sorting nodes question kevin_in_black XSLT 2 April 13th, 2004 05:51 AM





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