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

Re: Is this about grouping ?

Subject: Re: Is this about grouping ?
From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx>
Date: Mon, 2 Jul 2001 17:06:12 +0100
access group concat
Hi Benoit,

> Of course, I should encapsulate <a> to <i> under <group>.
>
> But still I'm stuck with my XSLT.

Leaving aside the indentation issue, and assuming that you use group
elements to indicate how the a and b elements apply to particular f to
i elements, you can do the following:

(a) declare the key to access the group elements according to a
particular combination of a and b.  You can use a concatenation of a
and b to give the key value for each group so that you are grouping by
the combination of the two values rather than by just one:

<xsl:key name="groups" match="group" use="concat(a, ':', b)" />

(b) apply templates to the first group with a particular a+b value.
You want to find the group that is the first group returned by the key
with that particular combination of a and b, and apply templates to
it:

<xsl:template match="topic">
  <topic>
    <xsl:apply-templates
      select="group[generate-id() =
                    generate-id(key('groups', concat(a, ':', b))[1])]" />
  </topic>
</xsl:template>

(c) have a template that matches a group, outputs the values of a and
b for that group and then copies the values of f to i of all the
groups with that particular a+b combination, as retrieved from the
key. You probably want to use a group element to distinguish the
output from this group from any others:

<xsl:template match="group">
  <group>
    <xsl:copy-of select="a" />
    <xsl:copy-of select="b" />
    <xsl:variable name="groups"
                  select="key('groups', concat(a, ':', b))" />
    <xsl:copy-of select="$groups/*[self::f or self::g or
                                   self::h or self::i]" />
  </group>
</xsl:template>

That's the Muenchian solution to the basic grouping problem. You have
a couple of additional twists which alter it a little. First, you
don't want to use a group element in the output to mark off the
groups, but instead indent the elements to varying degrees. I think
this is a dangerous way of indicating structure in an XML document
because whitespace is often ignored (especially if you use MSXML),
which means you lose precious information.

If you really want to use indentation, then you need to use xsl:text
elements to include the significant whitespace. In your sample XSLT,
you've been using *empty* xsl:text elements to mark off whitespace -
this is a technique that only works if you have some non-whitespace
characters alongside the whitespace ones; if you want to include a
number of spaces, you have to put that in the *content* of the
xsl:text, e.g.:

  <xsl:for-each select="$elements">
     <xsl:text>&#xA;      </xsl:text>
     <xsl:copy-of select="." />
  </xsl:for-each>

(The &#xA; gives a line break.)

The second complication arises if you don't use group elements in your
source XML. That means you have to use some other element to indicate
the groups - the a element is a good bet - and use the
following-sibling axis to access the relevant elements:

<xsl:key name="groups" match="group"
         use="concat(., ':', following-sibling::b[1])" />

<xsl:template match="topic">
  <topic>
    <xsl:apply-templates
      select="a[generate-id() =
                generate-id(key('groups',
                                concat(a, ':',
                                       following-sibling::b[1]))[1])]" />
  </topic>
</xsl:template>

<xsl:template match="a">
  <group>
    <xsl:copy-of select="." />
    <xsl:variable name="b" select="following-sibling::b[1]" />
    <xsl:copy-of select="$b" />
    <xsl:variable name="groups"
                  select="key('groups', concat(., ':', $b))" />
    <xsl:copy-of select="$groups/following-sibling::f[1] |
                         $groups/following-sibling::g[1] |
                         $groups/following-sibling::h[1] |
                         $groups/following-sibling::i[1]" />
  </group>
</xsl:template>

Or you might find that a different type of grouping method, such as
one that steps through the elements one by one to create the groups,
is easier to handle.

Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


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.