RE: [xsl] Grouping with keys

Subject: RE: [xsl] Grouping with keys
From: "Rick Quatro" <rick@xxxxxxxxxxxxxx>
Date: Thu, 24 Oct 2013 16:11:15 -0400
Pedantic is good. Let me work through the example and try to understand it.
I think I am close to the eureka moment :-). Thanks for your help.

Rick

-----Original Message-----
From: G. Ken Holman [mailto:g.ken.holman@xxxxxxxxx] On Behalf Of G. Ken
Holman
Sent: Thursday, October 24, 2013 3:57 PM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx; xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: RE: [xsl] Grouping with keys

At 2013-10-24 15:31 -0400, Rick Quatro wrote:
>Thanks for reply. I can't really key on the <p> elements because there 
>could be different elements before the first <li> in a group.

Sure ... but you could then key on anything that isn't an <li>.

>I want to key on the
>first <li> in each group regardless of its immediate preceding sibling.

I would rather key on the last element before each first <li>, not on the
<li> itself.  That is where I think you are going too deep:  when you find
yourself in the nodes to be handled with special handling, it is too awkward
to handle them specially.  I try to stay away from the nodes and handle them
"outside" of themselves.  Or have I said that correctly?  Back to the XSLT
design approach of looking at things "top-down", I want to handle the <li>
grouping at arm's length, not while I'm in the <li> being grouped.  That is
going too far.

Forgive me if I sound pedantic, but you said in your earlier note you really
wanted to understand this.

Just keep thinking "top-down" and how it is easier to handle items from
arm's  length rather than from inside.

>Also, I want to use template rules instead of pull processing.

That is a straightforward adaptation.  In my solution you'll see that I'm
using the push model and the special handling of grouping is done agnostic
of the element (provided it isn't an li).  In the grouping I add the
inferred structure.  The handling of everything else is done independent of
the grouping logic.

I hope you find the version below helpful.

. . . . . . . .  Ken


t:\ftemp>type rick.xml
<body>
   <li>one</li>
   <li>two</li>
   <p>paragraph</p>
   <li>three</li>
   <li>four</li>
   <p>paragraph</p>
   <li>five</li>
   <li>six</li>
</body>
t:\ftemp>call xslt rick.xml rick.xsl
<?xml version="1.0" encoding="utf-8"?>
<body>
    <ol>
       <li>one</li>
       <li>two</li>
    </ol>
    <p>paragraph</p>
    <ol>
       <li>three</li>
       <li>four</li>
    </ol>
    <p>paragraph</p>
    <ol>
       <li>five</li>
       <li>six</li>
    </ol>
</body>
t:\ftemp>type rick.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
   version="1.0">

<xsl:key name="li" match="li"
 
use="generate-id((..|preceding-sibling::*[not(self::li)][1])[last()])"/>

<xsl:output indent="yes"/>

<!--this is a construct whose children need to be grouped in separate
lists--> <xsl:template match="body">
   <body>
     <xsl:apply-templates mode="group" select=".|*[not(self::li)]"/>
   </body>
</xsl:template>

<xsl:template mode="group" match="*">
   <xsl:apply-templates select="self::*[not(self::body)]"/>
   <xsl:if test="key('li',generate-id(.))">
     <ol>
       <xsl:apply-templates select="key('li',generate-id(.))"/>
     </ol>
   </xsl:if>
</xsl:template>

<!--the following template rules need no knowledge of grouping-->

<xsl:template match="p">
   <p><xsl:apply-templates/></p>
</xsl:template>

<xsl:template match="li">
   <li><xsl:apply-templates/></li>
</xsl:template>

</xsl:stylesheet>
t:\ftemp>rem Done!


--
Public XSLT, XSL-FO, UBL & code list classes: Melbourne, AU May 2014 |
Contact us for world-wide XML consulting and instructor-led training | Free
5-hour lecture: http://www.CraneSoftwrights.com/links/udemy.htm |
Crane Softwrights Ltd.            http://www.CraneSoftwrights.com/s/ |
G. Ken Holman                   mailto:gkholman@xxxxxxxxxxxxxxxxxxxx |
Google+ profile: https://plus.google.com/116832879756988317389/about |
Legal business disclaimers:    http://www.CraneSoftwrights.com/legal |

Current Thread