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 February 7th, 2008, 06:28 AM
Registered User
 
Join Date: Jan 2008
Posts: 9
Thanks: 0
Thanked 0 Times in 0 Posts
Default first n elements with highest counts in a group


Hi All,

I did a transformation of a XML file.The description is given below-

input XML

<?xml version="1.0" encoding="ISO-8859-1"?>
<School>
<student rec='1'>
<name>Robart J</name>
</student>
<student rec='2'>
<name>Alex M; Peter R; Robart J</name>
</student>
<student rec='3'>
<name>Alex M;Robart J; Dave T</name>
</student>
<student rec='4'>
<name>Alex M;Robart J; Peter R</name>
</student>
</School>

XSLT , I used-
<School>
<xsl:for-each-group select=" School/student group-by="name/tokenize(., ';\s*')">
<xsl:sort select="current-grouping-key()"/>
<name count="{count(current-group())}">
<xsl:value-of select="current-grouping-key()"/>
</name>
</xsl:for-each-group>
</School>

Output I got-
<School>
<name count='4'>Robart J</name>
<name count='3'>Alex M</name>
<name count='2'>Peter R</name>
<name count='1'>Dave T</name>
</School>

Now I want a little change in output format. Instead of writing all the name elements I want to write only two name elements having highest count value.Like-
<School>
<name count='4'>Robart J</name>
<name count='3'>Alex M</name>
</School>

When I tried with this XSLT code-
<School>
<xsl:for-each-group select=" School/student group-by="name/tokenize(., ';\s*')">
<xsl:sort data-type="number" select="count(current-group())" order="descending" />
<xsl:sort select="current-grouping-key()"/>
<xsl:for-each select="current-group()" >
<xsl:if test="position()=2">
<name count="{count(current-group())}">
<xsl:value-of select="current-grouping-key()"/>
</name>
</xsl:if>
</xsl:for-each>
</xsl:for-each-group>
</School>

I m getting output like-
<School>
<name count='4'>Robart J</name>
<name count='3'>Alex M</name>
<name count='2'>Peter R</name>
</School>

That is all the name elements having more than or equal to 2 count value. But I wanted only the first two name elements having highest counts.
Thanks for help.
 
Old February 7th, 2008, 11:23 AM
Registered User
 
Join Date: Jan 2008
Posts: 9
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Michael suggested one modification in the code I was trying as below-

<School>
  <xsl:for-each-group select=" School/student
                      group-by="name/tokenize(., ';\s*')">
    <xsl:sort data-type="number" select="count(current-group())"
order="descending" />
    <xsl:sort select="current-grouping-key()"/>
    <xsl:if test="position() <= 2">
      <name count="{count(current-group())}">
        <xsl:value-of select="current-grouping-key()"/>
      </name>
    </xsl:if>
  </xsl:for-each-group>
</School>

And it is working.

Thanks Michael.
 
Old February 7th, 2008, 11:25 AM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

I think the following code produces the result you want:
Code:
      <xsl:for-each-group select="School/student" group-by="name/tokenize(., ';\s*')">
        <xsl:sort select="count(current-group())" order="descending"/>
        <xsl:if test="position() = (1, 2)">
        <name count="{count(current-group())}">
          <xsl:value-of select="current-grouping-key()"/>
        </name>
        </xsl:if>
      </xsl:for-each-group>
 
Old February 8th, 2008, 07:21 AM
Registered User
 
Join Date: Jan 2008
Posts: 9
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Thanks Martin for your input.

I tried the code suggested by you and Michael, both are working fine with saxon processor but when i used it with Altova, I was getting very odd output. Might be this is a problem of Altova.

Regards,
Manish
 
Old February 8th, 2008, 10:15 AM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

I have tried Altova's command line tool in the version "AltovaXML Version 2008 sp1" and the result I get with my stylesheet is the same as the result with Saxon 9.

 
Old February 8th, 2008, 11:11 AM
samjudson's Avatar
Friend of Wrox
 
Join Date: Aug 2007
Posts: 2,128
Thanks: 1
Thanked 189 Times in 188 Posts
Default

The answer I would give (having had a little experience with Altova's XSLT processor) is definitely. I frequently got 'weird' results, especially when using xsl:for-each-group instructions.

/- Sam Judson : Wrox Technical Editor -/
 
Old February 8th, 2008, 09:16 PM
Friend of Wrox
 
Join Date: Jul 2006
Posts: 430
Thanks: 28
Thanked 5 Times in 5 Posts
Send a message via Yahoo to bonekrusher
Default

I find that the Saxon processor is much better and faster. Saxon supports the collection() function which is extremely powerful, especially when using the for-each-group. I use XMLspy to edit, but SAXON to do my XSLT 2.0 productions. I wish Altova would just use the Saxon9api.

my 2 cents.

Bones







Similar Threads
Thread Thread Starter Forum Replies Last Post
Xsl: strip-space elements; and 'group-adjacent' ROCXY XSLT 6 July 15th, 2010 08:59 AM
How to group xsl elements in xslt.10 suji XSLT 1 February 29th, 2008 03:44 AM
Multiple doc'ts w/ specific record elements counts kapy_kal XSLT 2 March 29th, 2006 11:25 AM
putting <element> round group of same elements jefke XSLT 0 May 24th, 2004 10:18 AM
how to arrange elements group wise. srini XSLT 0 February 4th, 2004 05:17 AM





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