[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: using xsl:for-each-group, grouping by child nodes?

Subject: Re: using xsl:for-each-group, grouping by child nodes?
From: Eric Scheid <eric.scheid@xxxxxxxxxxxxxxx>
Date: Mon, 06 Oct 2008 01:06:13 +1100
Re:  using xsl:for-each-group
On 5/10/08 7:48 AM, "G. Ken Holman" <gkholman@xxxxxxxxxxxxxxxxxxxx> wrote:

> Then use XSLT 1.0 to solve the problem ... no reason to give up.
>
> I hope the below helps.

Thanks for this, I was all set to pre-process it inside the database and
export munged data (eg. flag fields indicating group starts). I really
appreciate your help here.

OK, this almost works for me - the xml I posted to the list was a bit
simplified and I must be screwing up the last bit of retrofitting. The
actual full XML is this:

<FMPXMLRESULT xmlns="http://www.filemaker.com/fmpxmlresult">
<ERRORCODE>0</ERRORCODE>
<PRODUCT BUILD="06-20-2006" NAME="FileMaker Pro" VERSION="8.5v1"/>
<DATABASE DATEFORMAT="D/m/yyyy" LAYOUT="" NAME="x-nested-muenchian-test.fp7"
RECORDS="6" TIMEFORMAT="h:mm:ss a"/>
<METADATA>
    <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="name" TYPE="TEXT"/>
    <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="number" TYPE="TEXT"/>
    <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="position" TYPE="TEXT"/>
    <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="state" TYPE="TEXT"/>
    <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="team" TYPE="TEXT"/>
</METADATA>
<RESULTSET FOUND="6">
     <ROW MODID="3" RECORDID="1">
         <COL><DATA>joe</DATA></COL>
         <COL><DATA>2</DATA></COL>
         <COL><DATA>pitcher</DATA></COL>
         <COL><DATA>ny</DATA></COL>
         <COL><DATA>mets</DATA></COL>
     </ROW>
     <ROW MODID="3" RECORDID="2">
         <COL><DATA>mark</DATA></COL>
         <COL><DATA>11</DATA></COL>
         <COL><DATA>outfielder</DATA></COL>
         <COL><DATA>ny</DATA></COL>
         <COL><DATA>mets</DATA></COL>
     </ROW>
     <ROW MODID="3" RECORDID="3">
         <COL><DATA>jane</DATA></COL>
         <COL><DATA>13</DATA></COL>
         <COL><DATA>outfielder</DATA></COL>
         <COL><DATA>ny</DATA></COL>
         <COL><DATA>cubs</DATA></COL>
     </ROW>
     <ROW MODID="3" RECORDID="4">
         <COL><DATA>mike</DATA></COL>
         <COL><DATA>7</DATA></COL>
         <COL><DATA>outfielder</DATA></COL>
         <COL><DATA>ny</DATA></COL>
         <COL><DATA>mets</DATA></COL>
     </ROW>
</RESULTSET>
</FMPXMLRESULT>

So I thought the code needed to be tweaked like this:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.1"
    xmlns:fmp="http://www.filemaker.com/fmpxmlresult"
    exclude-result-prefixes='fmp'
    >
<xsl:output
    method="text"
    version="1.0"
    encoding="UTF-8" />

<xsl:template match="/fmp:FMPXMLESULT">
   <!--group first by team; using a key of two parts with an unlikely
       character in between to avoid any ambiguous concatenations-->
   <xsl:variable name="players" select="/fmp:FMPXMLESULT/*/fmp:ROW"/>
   <xsl:for-each select="$players">
     <xsl:if test="generate-id(.)=
        generate-id($players[concat(
            fmp:COL[4]/fmp:DATA,'&#xd;',fmp:COL[5]/fmp:DATA)=
               concat(current()/fmp:COL[4]/fmp:DATA, '&#xd;',
                      current()/fmp:COL[5]/fmp:DATA)][1])">
       <!--found the first player for a given team-->
       <xsl:if test="generate-id(.)!=generate-id($players[1])">
         <xsl:text>&#xa;</xsl:text>
       </xsl:if>
       <xsl:text>&#xa;    Team: </xsl:text>
       <xsl:value-of select="concat(fmp:COL[5]/fmp:DATA,',
            ',fmp:COL[4]/fmp:DATA)"/>
       <xsl:variable name="team"
            select="$players[concat(fmp:COL[4]/fmp:DATA, '&#xd;',
                fmp:COL[5]/fmp:DATA) = concat(
                  current()/fmp:COL[4]/fmp:DATA, '&#xd;',
                  current()/fmp:COL[5]/fmp:DATA)]"/>
       <!--now group by position; reflecting plural where applicable-->
       <xsl:for-each select="$team">
         <xsl:if test="generate-id(.) =
                  generate-id($team[fmp:COL[3]/fmp:DATA =
                               current()/fmp:COL[3]/fmp:DATA][1])">
           <xsl:text>&#xa;       </xsl:text>
           <xsl:value-of select="fmp:COL[3]/fmp:DATA"/>
           <xsl:variable name="position"
                select="$team[fmp:COL[3]/fmp:DATA =
                         current()/fmp:COL[3]/fmp:DATA]"/>
           <xsl:if test="count($position)>1">s</xsl:if>:<xsl:text/>
           <!--show all in the position-->
           <xsl:for-each select="$position">
             <xsl:text>&#xa;           </xsl:text>
             <xsl:value-of
                  select="concat(fmp:COL[1]/fmp:DATA,',
                                 ',fmp:COL[2]/fmp:DATA)"/>
           </xsl:for-each>
         </xsl:if>
       </xsl:for-each>
     </xsl:if>
   </xsl:for-each>
</xsl:template>

(btw, is there any short-hand way to avoid having to specify the fmp9
prefix everywhere like this?)

but I9m getting the wrong output:

0joe2pitchernymetsmark11outfieldernymetsjohn23pitchernymetspete27outfieldern
ycubsroy13outfieldernycubscarl32infieldernycubs

My eyes are tired - I probably did something stupid.

I see you run training courses .. are you thinking of coming to Sydney
anytime soon?

e.

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.