Re: [xsl] Grouping based on key result

Subject: Re: [xsl] Grouping based on key result
From: Ganesh Babu N <nbabuganesh@xxxxxxxxx>
Date: Thu, 5 Mar 2009 16:17:17 +0530
Here is my XML content:

<author-group>
   <author>
      <given-name>T.</given-name>
      <surname>Miwa</surname>
      <cross-ref refid="aff2"><sup>b</sup></cross-ref>
   </author>
   <author>
      <given-name>T.</given-name>
      <surname>Nomura</surname>
      <cross-ref refid="aff2"><sup>b</sup></cross-ref>
   </author>
   <author>
       <given-name>J.</given-name>
       <surname>Sakakibara</surname>
       <cross-ref refid="aff1"><sup>a</sup></cross-ref>
   </author>
   <author>
       <given-name>H.</given-name>
       <surname>Shintani</surname>
       <cross-ref refid="aff1"><sup>a</sup></cross-ref>
   </author>
   <author>
    <initials>B.E.</initials>
    <given-name>B.E.</given-name>
    <surname>Ungerechts</surname>
    <cross-ref refid="aff3"><sup>c</sup></cross-ref>
   </author>

   <affiliation id="aff1"><label>a</label><textfn>Graduate School of
Systems and Information Engineering, University of Tsukuba, Tsukuba
305-8573, Japan</textfn></affiliation>

   <affiliation id="aff2"><label>b</label><textfn>Graduate School of
Comprehensive Human Sciences, University of Tsukuba, Tsukuba 305-8573,
Japan</textfn></affiliation>

   <affiliation id="aff3"><label>c</label><textfn>Institute of Sport
Sciences, University of Bielefeld, D-33615 Bielefeld,
Germany</textfn></affiliation>

My code1:

<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
               xmlns:xs="http://www.w3.org/2001/XMLSchema";
               xmlns:f="data:,f"
               exclude-result-prefixes="xs f">

<xsl:output indent="yes" encoding="US-ASCII"/>
<xsl:strip-space elements="*"/>

<xsl:key name="country" match="affiliation/textfn"
use="parent::affiliation/@id"/>
<xsl:template match="author-group">
    <xsl:for-each-group select="author" group-adjacent="f:country(.)">
       <xsl:apply-templates select="current-group()"/>
      (<xsl:value-of select="current-grouping-key()"/>)
    </xsl:for-each-group>

</xsl:template>

<xsl:template match="author">
 <xsl:choose>
   <xsl:when test="[position() = last() and position() != 1]">
      <xsl:text> and </xsl:text>
      <author><xsl:value-of select="given-name,surname"/></author>
   </xsl:when>
   <xsl:when test="position() != 1">
      <xsl:text>, </xsl:text>
      <author><xsl:value-of select="given-name,surname"/></author>
   </xsl:when>
   <xsl:otherwise>
      <author><xsl:value-of select="given-name,surname"/></author>
   </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<xsl:function name="f:country" as="xs:string">
 <xsl:param name="a" as="element()"/>
 <xsl:choose>
 <xsl:when test="$a/cross-ref">
  <xsl:sequence select="key('country',
$a/cross-ref/@refid,root($a))/tokenize(.,',\s+')[last()]"/>
 </xsl:when>
 <xsl:otherwise>
    <xsl:sequence
select="$a/following-sibling::affiliation[1]/tokenize(.,',\s+')[last()]"/>
 </xsl:otherwise>
 </xsl:choose>
</xsl:function>

</xsl:stylesheet>

With the code I am getting the out put as :
<author>T.Miwa</author>, 	<author>T.Nomura</author>,
<author>J.Sakakibara</author> and <author>H.Shintani</author> (Japan)
<author>B.E.Ungerechts</author> (Germany)

But the desired output is:

<author>T.Miwa</author>, 	<author>T.Nomura</author>,
<author>J.Sakakibara</author>,  <author>H.Shintani</author> (Japan)
and <author>B.E.Ungerechts</author> (Germany)

Means irrespective of the grouping the "and" should be placed before
the last author.

My Code 2:

<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
               xmlns:xs="http://www.w3.org/2001/XMLSchema";
               xmlns:f="data:,f"
               exclude-result-prefixes="xs f">

<xsl:output indent="yes" encoding="US-ASCII"/>
<xsl:strip-space elements="*"/>

<xsl:key name="country" match="affiliation/textfn"
use="parent::affiliation/@id"/>
<xsl:template match="author-group">
<xsl:if test="author[position() = last() and position() != 1]">
	<xsl:text> and </xsl:text>
    <xsl:for-each-group select="author" group-adjacent="f:country(.)">
       <xsl:apply-templates select="current-group()"/>
      (<xsl:value-of select="current-grouping-key()"/>)
    </xsl:for-each-group>
</xsl:if>
</xsl:template>

<xsl:template match="author">
      <author><xsl:value-of select="given-name,surname"/></author>
</xsl:template>

<xsl:function name="f:country" as="xs:string">
 <xsl:param name="a" as="element()"/>
 <xsl:choose>
 <xsl:when test="$a/cross-ref">
  <xsl:sequence select="key('country',
$a/cross-ref/@refid,root($a))/tokenize(.,',\s+')[last()]"/>
 </xsl:when>
 <xsl:otherwise>
    <xsl:sequence
select="$a/following-sibling::affiliation[1]/tokenize(.,',\s+')[last()]"/>
 </xsl:otherwise>
 </xsl:choose>
</xsl:function>

</xsl:stylesheet>

With the code I am getting the out put as :
and <author>T.Miwa</author>, 	<author>T.Nomura</author>,
<author>J.Sakakibara</author>  <author>H.Shintani</author> (Japan)
<author>B.E.Ungerechts</author> (Germany)

But the desired output is:

<author>T.Miwa</author>, 	<author>T.Nomura</author>,
<author>J.Sakakibara</author>,  <author>H.Shintani</author> (Japan)
and <author>B.E.Ungerechts</author> (Germany)

Please help me in achieving the desired output.

Regards,
Ganesh




On Thu, Mar 5, 2009 at 3:01 PM, Michael Kay <mike@xxxxxxxxxxxx> wrote:
> Please show your code. It's very hard to debug your code based on an
English
> description of your code, it's much easier to spot your mistakes if we can
> see the actual code.
>
> Michael Kay
> http://www.saxonica.com/
>
>> -----Original Message-----
>> From: Ganesh Babu N [mailto:nbabuganesh@xxxxxxxxx]
>> Sent: 05 March 2009 09:18
>> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
>> Subject: Re: [xsl] Grouping based on key result
>>
>> Thanks David,
>>
>> Another problem pertaining to the same solution.
>>
>> I have 5 authors. 4 belongs Japan and 1 belongs to Germany
>>
>> I need to place "and" before the last author. i.e. before the
>> 5th author
>>
>> I have implemented this in author template. position[last()]
>> and position() != 1
>>
>> As we are applying the author template inside grouping, the
>> "and" is coming before 4 th author and not before 5th author.
>>
>> Desired output:
>>
>> <author>T.Miwa</author><author>T.Nomura</author><author>J.Saka
> kibara</author><author>H.Shintani</author>
>> (Japan) and <author>B.E.Ungerechts</author> (Germany)
>>
>>
>> Output got:
>>
>> <author>T.Miwa</author><author>T.Nomura</author><author>J.Saka
> kibara</author>
>>  and  <author>H.Shintani</author>
>> (Japan)<author>B.E.Ungerechts</author> (Germany)
>>
>> I have also tried putting this condition outside
>> for-each-group but it is not working.
>>
>> The script should place the "and" irrespective of grouping.
>>
>> Please help me how to achieve desired output.
>>
>>
>> Regards,
>> Ganesh
>>
>> On Tue, Mar 3, 2009 at 6:57 PM, David Carlisle
>> <davidc@xxxxxxxxx> wrote:
>> >
>> >
>> >> For one there is cross-ref and for another there is no. In these
>> >> cases also it should do the grouping.
>> >
>> >
>> > <xsl:function name="f:country" as="xs:string">
>> >  <xsl:param name="a" as="element()"/>
>> >  <xsl:choose>
>> >  <xsl:when test="$a/cross-ref">
>> >   <xsl:sequence select="key('country',
>> > $a/cross-ref/@refid,root($a))/tokenize(.,',\s+')[last()]"/>
>> >  </xsl:when>
>> >  <xsl:otherwise>
>> >     <xsl:sequence
>> >
>> select="$a/following-sibling::affiliation[1]/tokenize(.,',\s+')[last()
>> > ]"/>
>> >  </xsl:otherwise>
>> >  </xsl:choose>
>> > </xsl:function>
>> >
>> >
>> ______________________________________________________________________
>> > __ The Numerical Algorithms Group Ltd is a company registered in
>> > England and Wales with company number 1249803. The
>> registered office
>> > is:
>> > Wilkinson House, Jordan Hill Road, Oxford OX2 8DR, United Kingdom.
>> >
>> > This e-mail has been scanned for all viruses by Star. The
>> service is
>> > powered by MessageLabs.
>> >
>> ______________________________________________________________________
>> > __

Current Thread