This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RE: Multi-level grouping problem. MSXML bug, maybe?


That's it! Thanks! I thought it had to be something like that, but I just
wasn't able to wrap my head around the second grouping level. I thought
getting D_CODE by type and subtype was kind of goofy, but I couldn't grasp
how getting "row" by type, subtype, and D_CODE would work.

That's why this list is a must-read for me. I've picked up so much in the
three weeks or so since I subscribed, I just can't even begin to explain.
And I thought I knew XSL pretty well already (I could get by, anyway).

Thanks again!

-----Original Message-----
From: Jeni Tennison [mailto:jeni@jenitennison.com]
Sent: Thursday, May 09, 2002 4:10 AM
To: mpfingstler@triseptsolutions.com
Cc: XSL-List@lists.mulberrytech.com
Subject: Re: [xsl] Multi-level grouping problem. MSXML bug, maybe?


Hi Mark,

> I want the output to look like:
>
> <?xml version="1.0" encoding="iso-8859-1"?>
> <CS>
>   <Co Type="F" SubType="S">
>     <DG Code="V" />
>     <DG Code="F" />
>   </Co>
>   <Co Type="F" SubType="T">
>     <DG Code="V" />
>   </Co>
> </CS>
>
> That is, I'm grouping by TYPE, SUB_TYPE, and D_CODE.

Yes, you've got two levels of grouping: one by TYPE and SUB_TYPE, and
one by D_CODE. Your key for grouping by TYPE and SUB_TYPE looks fine:

> <xsl:key name="row-by-type-subtype" match="row"
>          use="concat(TYPE/@value, '|', SUB_TYPE/@value)"/>

But your key for grouping by D_CODE is off. You have:

> <xsl:key name="d-by-type-subtype" match="D_CODE"
>          use="concat(../TYPE/@value, '|', ../SUB_TYPE/@value)"/>

This groups the D_CODE elements by their row's TYPE and SUB_TYPE; in
other words, it does exactly the same as the first key, except
grouping the D_CODE elements rather than the rows.

You want to group the *rows* by their D_CODE values. And because it's
the second level in the grouping, you need to incorporate the TYPE and
SUB_TYPE into that as well. So the key should look like:

<xsl:key name="row-by-d-code" match="row"
  use="concat(TYPE/@value, '|', SUB_TYPE/@value, '|', D_CODE/@value)"/>

Then you just do what you're doing, but use this key to filter the
rows with a particular TYPE and SUB_TYPE down to those with a unique
D_CODE as well:

  <xsl:for-each select="/recordset/row[count(. |
  key('row-by-type-subtype', concat(TYPE/@value, '|', SUB_TYPE/@value))[1])
= 1]">
    <xsl:variable name="type" select="TYPE/@value"/>
    <xsl:variable name="subtype" select="SUB_TYPE/@value"/>
    <xsl:variable name="type-subtype"
                  select="concat($type, '|', $subtype)" />
    <Co Type="{$type}" SubType="{$subtype}">
      <xsl:for-each select="key('row-by-type-subtype', $type-subtype)
        [count(.|key('row-by-d-code',
                     concat($type-subtype, '|', D_CODE/@value))[1])=1">
        <DG Code="{D_CODE/@value}" />
      </xsl:for-each>
    </Co>
  </xsl:for-each>

----

The XSLT 2.0 version:

  <xsl:for-each-group select="/recordset/row"
      group-by="concat(TYPE/@value, '|', SUB_TYPE/@value)">
    <Co Type="{TYPE/@value}" SubType="{SUB_TYPE/@value}">
      <xsl:for-each-group select="current-group()"
                          group-by="D_CODE/@value">
        <DG Code="{D_CODE/@value}" />
      </xsl:for-each-group>
    </Co>
  </xsl:for-each-group>
  
Cheers,

Jeni

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

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]