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 July 10th, 2006, 02:27 PM
Registered User
 
Join Date: Jul 2006
Posts: 2
Thanks: 0
Thanked 0 Times in 0 Posts
Default Advanced grouping XSLT 2

I'm using Saxon 8.7 to solve the following problem:

XML Source:
<root>
    <heading1>
        <plain>plain text</plain>>
        <plain>plain text</plain>
        <plain>plain text</plain>
        <plain>plain text</plain>
        <plain>plain text</plain>
        <jtext>jtext jtext jtext jtext jtext</jtext>
        <jtext>jtext jtext jtext jtext jtext</jtext>
        <jheader>a jkopjheader</jheader>
        <jtext>jtext jtext jtext jtext jtext</jtext>
        <jtext>jtext jtext jtext jtext jtext</jtext>
        <jtext>jtext jtext jtext jtext jtext</jtext>
        <jtext>jtext jtext jtext jtext jtext</jtext>
        <btext>my btext</btext>
        <plain>plain text</plain>
        <plain>plain text</plain>
        <plain>plain text</plain>
        <plain>plain text</plain>
        <plain>plain text</plain>
        <jheader>a jheader</jheader>
        <jtext>jtext jtext jtext jtext jtext</jtext>
        <jtext>jtext jtext jtext jtext jtext</jtext>
        <jtext>jtext jtext jtext jtext jtext</jtext>
        <jtext>jtext jtext jtext jtext jtext</jtext>
        <btext>my btext</btext>
    </heading1>
</root>

Desired output:
<root>
    <heading1>
        <plaingroup>
            <plain>plain text</plain>
            <plain>plain text</plain>
            <plain>plain text</plain>
            <plain>plain text</plain>
            <plain>plain text</plain>
        </plaingroup>
        <jgroup>
            <jtext>jtext jtext jtext jtext jtext</jtext>
            <jtext>jtext jtext jtext jtext jtext</jtext>
        </jgroup>
        <jgroup>
            <jheader>a jheader</jheader>
            <jtext>jtext jtext jtext jtext jtext</jtext>
            <jtext>jtext jtext jtext jtext jtext</jtext>
            <jtext>jtext jtext jtext jtext jtext</jtext>
            <jtext>jtext jtext jtext jtext jtext</jtext>
            <btext>my btext</btext>
        </jgroup>
        <plaingroup>
            <plain>plain text</plain>
            <plain>plain text</plain>
            <plain>plain text</plain>
            <plain>plain text</plain>
            <plain>plain text</plain>
        </plaingroup>
        <jgroup>
            <jheader>a jheader</jheader>
            <jtext>jtext jtext jtext jtext jtext</jtext>
            <jtext>jtext jtext jtext jtext jtext</jtext>
            <jtext>jtext jtext jtext jtext jtext</jtext>
            <jtext>jtext jtext jtext jtext jtext</jtext>
            <btext>my btext</btext>
        </jgroup>
    </heading1>
</root>

My stylesheet until now:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:strip-space elements="*"/>

    <xsl:template match="root">
        <xsl:element name="{name()}">
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="heading1">
        <xsl:element name="{name()}">
            <xsl:for-each-group select="*" group-adjacent="self::*">
                <xsl:choose>
                    <xsl:when test="self::plain">
                        <plaingroup>
                            <xsl:for-each-group select="current-group()" group-adjacent="self::plain">
                                <xsl:copy-of select="current-group()"/>
                            </xsl:for-each-group>
                        </plaingroup>
                    </xsl:when>
                    <xsl:when test="self::jkop">
                        <jgroup>
                            <xsl:for-each-group select="current-group()" group-adjacent="self::jheader or self::jtext or self::btext">
                                <xsl:copy-of select="current-group()"/>
                            </xsl:for-each-group>
                        </jgroup>
                    </xsl:when>
                    <xsl:when test="self::jtext">
                        <jgroup>
                            <xsl:for-each-group select="current-group()" group-adjacent="self::jtext or self::btext">
                                <xsl:copy-of select="current-group()"/>
                            </xsl:for-each-group>
                        </jgroup>
                    </xsl:when>
                    <xsl:when test="self::btext">
                        <jgroup>
                            <xsl:for-each-group select="current-group()" group-adjacent="self::jtext | self::btext">
                                <xsl:copy-of select="current-group()"/>
                            </xsl:for-each-group>
                        </jgroup>
                    </xsl:when>
                    <xsl:otherwise>
                        <unknown>
                            <xsl:copy-of select="current-group()"/>
                        </unknown>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each-group>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>


The key problem for me is to understand the group-adjacent attribute. I can't figure out how it exactly works. Does anyone has a small sample or hint to put me in the right direction?

Thanks & Regards,

Geurt Lagemaat.

 
Old July 10th, 2006, 03:12 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

group-adjacent defines the value that adjacent things have in common if they are to go in the same group. In your case, for the most part you are grouping elements that have the same name, that is:

group-adjacent="node-name(.)"

Writing group-adjacent="self::*" (or just group-adjacent=".") would be appropriate if it's the value (content) of the elements that matters rather than their name.

I don't know how completely your example describes the problem, but I think I'd be inclined to tackle it using group-starting-with. Something like:

group-starting-with="plain[not(preceding-sibling::*[1][self::plain])] | jheader | jtext[not(preceding-sibling::*[1][self::jtext or self::jheader])]"

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old July 11th, 2006, 03:07 PM
Registered User
 
Join Date: Jul 2006
Posts: 2
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Quote:
quote:Originally posted by mhkay
 group-adjacent defines the value that adjacent things have in common if they are to go in the same group. In your case, for the most part you are grouping elements that have the same name, that is:

group-adjacent="node-name(.)"
Thank you for you’re help. I didn’t read you’re book to well… I was thinking that I could use the group-adjacent attribute as some sort selection of element names that make up a group. You put me in the right direction with the group-starting-with attribute. My stylesheet now looks like:

<?xml version="1.0"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:strip-space elements="*"/>

    <xsl:template match="root">
        <xsl:element name="{name()}">
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="heading1">
        <xsl:element name="{name()}">
            <xsl:for-each-group select="*" group-starting-with="plain[not(preceding-sibling::*[1][self::plain])] | jheader | jtext[not(preceding-sibling::*[1][self::jheader or self::jtext or self::btext])] | btext[not(preceding-sibling::*[1][self::jheader or self::jtext or self::btext])]">
                <xsl:choose>
                    <xsl:when test="self::plain">
                        <plaingroup>
                            <xsl:copy-of select="current-group()"/>
                        </plaingroup>
                    </xsl:when>
                    <xsl:otherwise>
                        <jgroup>
                            <xsl:copy-of select="current-group()"/>
                        </jgroup>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each-group>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>


and is working correctly.

Thanks again, Geurt Lagemaat







Similar Threads
Thread Thread Starter Forum Replies Last Post
Grouping with XSLT 1.0 rodmcleay XSLT 1 January 14th, 2008 11:42 PM
XSLT Grouping vernc XSLT 2 October 2nd, 2007 03:59 AM
XSLT 1.0 Grouping kwilliams XSLT 0 January 11th, 2006 06:30 PM
XSLT Grouping Help Missy XSLT 0 December 14th, 2005 10:28 PM
Advanced Grouping Using the Muenchian Method Bodiam XSLT 0 August 8th, 2005 11:33 AM





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