Wrox Programmer Forums

Need to download code?

View our list of code downloads.

Go Back   Wrox Programmer Forums > XML > XSLT
Password Reminder
Register
Register | FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read
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 tens of thousands of software programmers and website developers including Wrox book authors and readers. As a guest, you can read any forum posting. By joining today you can post your own programming questions, respond to other developersí questions, and eliminate the ads that are displayed to guests. Registration is fast, simple and absolutely free .
DRM-free e-books 300x50
Reply
 
Thread Tools Display Modes
  #1 (permalink)  
Old June 20th, 2013, 05:24 PM
Authorized User
Points: 71, Level: 1
Points: 71, Level: 1 Points: 71, Level: 1 Points: 71, Level: 1
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Jan 2012
Posts: 17
Thanks: 7
Thanked 0 Times in 0 Posts
Default for-each-group, group-adjacent confusion

Hi all,
I'm having some trouble with getting my groups correct with for-each-group. I'm able to group by <coll>, but I would like to avoid repeating the <county>. I've placed my style sheet below the desired output. Any suggestions would be greatly appreciated.

I've attempted a few different variations using group-adjacent but I'm missing something. Thank you for your time & trouble. I'm using XSLT 2.0.

I have the following input file:
Code:
<base>
    <item>
        <coll>AAA</coll>
        <inst>horn</inst>
        <name>Andy</name>
        <county>AlphaC</county>
    </item>
    <item>
        <coll>BBB</coll>
        <inst>chimes</inst>
        <name>Bob</name>
        <county>BravoC</county>
    </item>
    <item>
        <coll>AAA</coll>
        <inst>bells</inst>
        <name>Cynthia</name>
        <county>CharlieC</county>
    </item>
    <item>
        <coll>CCC</coll>
        <inst>flute</inst>
        <name>Daria</name>
        <county>BravoC</county>
    </item>
    <item>
        <coll/>
        <inst>horn</inst>
        <name>Edgar</name>
        <county>DeltaC</county>
    </item>
    <item>
        <coll>AAA</coll>
        <inst>drum</inst>
        <name>Fred</name>
        <county>AlphaC</county>
    </item>
</base>
I would like to output the following:
Code:
<newDoc>
   <group>
      <doc>Edgar-docTitle</doc>
      <title/>
      <subject>Edgar</subject>
      <subject>DeltaC</subject>
   </group>
   <group>
      <doc>AAA-docTitle</doc>
      <title>AAA</title>
      <subject>Andy</subject>
      <subject>Cynthia</subject>
      <subject>Fred</subject>
      <subject>AlphaC</subject>
      <subject>CharlieC</subject>
   </group>
   <group>
      <doc>BBB-docTitle</doc>
      <title>BBB</title>
      <subject>Bob</subject>
      <subject>BravoC</subject>
   </group>
   <group>
      <doc>CCC-docTitle</doc>
      <title>CCC</title>
      <subject>Daria</subject>
      <subject>BravoC</subject>
   </group>
</newDoc>
This is my style sheet:
Code:
<?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
        
        <xsl:strip-space elements="*"/>
        <xsl:output method="xml" indent="yes"/>
        
        <xsl:template match="/">
            <newDoc>
            <xsl:for-each-group select="base/item" group-by="coll">
                <xsl:sort select="current-grouping-key()"/>
                <xsl:variable name="vResultName">
                    <xsl:choose>
                        <!-- doesn't work. keep working on this. -->
                        <xsl:when test="current-grouping-key() = ''">
                            <xsl:value-of select="concat(name[1], '-docTitle')"/>
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:value-of select="concat(current-grouping-key(), '-docTitle')"/>
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:variable>
                <group>
                    <doc>
                        <xsl:value-of select="$vResultName"/>
                    </doc>
                    <title>
                        <xsl:value-of select="current-grouping-key()"/>
                    </title>
                    <xsl:for-each select="current-group()">
                        <subject>
                            <xsl:value-of select="name"/>        
                        </subject>
                    </xsl:for-each>
                    <!-- grab county element, unique only -->
                    <xsl:for-each-group select="current-group()" group-adjacent="county">
                        <xsl:sort select="current-grouping-key()"/>
                        <subject>
                            <xsl:value-of select="current-grouping-key()"/>
                        </subject>
                    </xsl:for-each-group>
                </group>    
            </xsl:for-each-group>
            </newDoc>    
        </xsl:template>
</xsl:stylesheet>

Last edited by CanOfBees; June 20th, 2013 at 05:25 PM. Reason: added [CODE]
Reply With Quote
  #2 (permalink)  
Old June 21st, 2013, 09:09 AM
Friend of Wrox
Points: 6,522, Level: 34
Points: 6,522, Level: 34 Points: 6,522, Level: 34 Points: 6,522, Level: 34
Activity: 50%
Activity: 50% Activity: 50% Activity: 50%
 
Join Date: Nov 2007
Location: Germany
Posts: 1,220
Thanks: 0
Thanked 237 Times in 236 Posts
Default

Here is a solution that creates the output you asked for:

Code:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output indent="yes"/>

<xsl:template match="base">
  <newDoc>
    <xsl:for-each-group select="item" group-by="coll/string(.)">
      <xsl:sort select="current-grouping-key()"/>
      <group>
        <doc>
          <xsl:sequence
            select="if (current-grouping-key() eq '')
                    then concat(name, '-docTitle')
                    else concat(current-grouping-key(), 'docTitle')"/>
        </doc>
        <title>
          <xsl:value-of select="current-grouping-key()"/>
        </title>
        <xsl:apply-templates select="current-group()/name"/>
        <xsl:for-each-group select="current-group()/county" group-by=".">
          <xsl:apply-templates select="."/>
        </xsl:for-each-group>
      </group>
    </xsl:for-each-group>
  </newDoc>
</xsl:template>

<xsl:template match="item/name | item/county">
  <subject>
    <xsl:value-of select="."/>
  </subject>
</xsl:template>

</xsl:stylesheet>
Main changes to your code:
If you want to include the value of empty elements in the collection of grouping keys you need to use 'group-by="coll/string(.)"' or at least 'group-by="normalize-string(coll)"' as otherwise the empty element does not contribute a grouping key.

And for the inner grouping I have just used group-by again, I am not sure why you tried with group-adjacent there.

Furthermore I have delegated the transformation of item/name and item/county to a template.
__________________
Martin Honnen
Microsoft MVP (XML, Data Platform Development) 2005/04 - 2013/03
My blog
Reply With Quote
The Following User Says Thank You to Martin Honnen For This Useful Post:
CanOfBees (June 21st, 2013)
  #3 (permalink)  
Old June 28th, 2013, 02:50 PM
Authorized User
Points: 71, Level: 1
Points: 71, Level: 1 Points: 71, Level: 1 Points: 71, Level: 1
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Jan 2012
Posts: 17
Thanks: 7
Thanked 0 Times in 0 Posts
Default

Martin,
apologies for the delayed response. Thank you for your time & trouble - your solution gave me the results I needed. Also, I appreciate the refactoring.

Best,
CoB
Reply With Quote
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are Off

Similar Threads
Thread Thread Starter Forum Replies Last Post
bunches of nodes, how to group them to different group using the business rules JohnKiller XSLT 9 March 7th, 2012 01:42 PM
Xsl: strip-space elements; and 'group-adjacent' ROCXY XSLT 6 July 15th, 2010 08:59 AM
Restart new group number in Group Footer sukarso Crystal Reports 2 October 13th, 2006 12:11 PM
Using - "group-adjacent" ROCXY XSLT 4 January 4th, 2006 10:09 AM
Using Two "group-adjacent" ROCXY XSLT 0 January 4th, 2006 07:29 AM



All times are GMT -4. The time now is 01:31 PM.


Powered by vBulletin®
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
© 2013 John Wiley & Sons, Inc.