 |
| 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
|
|
|
|

July 6th, 2009, 04:04 PM
|
|
Authorized User
|
|
Join Date: Jul 2009
Posts: 25
Thanks: 1
Thanked 0 Times in 0 Posts
|
|
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..
|
|

July 6th, 2009, 04:31 PM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
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
|
|

July 6th, 2009, 04:53 PM
|
|
Authorized User
|
|
Join Date: Jul 2009
Posts: 25
Thanks: 1
Thanked 0 Times in 0 Posts
|
|
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
|
|

July 6th, 2009, 05:52 PM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
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
|
|

July 7th, 2009, 01:32 AM
|
|
Authorized User
|
|
Join Date: Jul 2009
Posts: 25
Thanks: 1
Thanked 0 Times in 0 Posts
|
|
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
|
|

July 7th, 2009, 03:40 AM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
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
|
|

July 7th, 2009, 07:49 AM
|
|
Authorized User
|
|
Join Date: Jul 2009
Posts: 25
Thanks: 1
Thanked 0 Times in 0 Posts
|
|
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
|
|

July 7th, 2009, 07:57 AM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
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
|
|

July 7th, 2009, 11:11 AM
|
|
Authorized User
|
|
Join Date: Jul 2009
Posts: 25
Thanks: 1
Thanked 0 Times in 0 Posts
|
|
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
|
|

July 8th, 2009, 01:19 AM
|
|
Friend of Wrox
|
|
Join Date: Jun 2008
Posts: 291
Thanks: 9
Thanked 29 Times in 29 Posts
|
|
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
|
|
 |