Subject: RE: [xsl] Trouble with grouping From: "David B. Bitton" <david@xxxxxxxxxxxxxx> Date: Wed, 06 Feb 2002 09:38:07 -0500 |
I can not say thank you enough. If you are ever in NYC, lemme know, I owe you a beer. For now, I'll just call you Dame Jeni Tennison, ok? :) > -----Original Message----- > From: Jeni Tennison [mailto:jeni@xxxxxxxxxxxxxxxx] > Sent: Wednesday, February 06, 2002 5:23 AM > To: David B. Bitton > Cc: xsl-list@xxxxxxxxxxxxxxxxxxxxxx > Subject: Re: [xsl] Trouble with grouping > > > Hi David, > > > I have found salvation within this list in regards to grouping and > > sorting before. I'm at my wits ends with this one. For some > reason, I > > am displaying records outside of the current context, and I cannot > > figure out why. Oh, and the additional records coming > through are not > > being displayed where their context is correct. The XSL and > XML files > > are a little to long to attach, so they are here: > > This is one of the classic problems with Muenchian grouping... > > Keys always index all the elements that match the pattern in > their match attribute *throughout the document*. So when you do: > > <xsl:key name="distinct" match="Transaction" use="IsCredit" /> > > You index *all* the Transaction elements in the document, > whatever Account they are in, based on their IsCredit value. > > When you try to get the unique ones within a particular > Account, with (in the context of an Account element): > > Transactions/Transaction[count(. | key('distinct', > IsCredit)[1]) = 1] > > then what you're actually doing is searching through the > Transaction elements within the Account, and locating those > that are first *in the entire document, across Accounts* with > a particular IsCredit value. That's why you're sometimes > *not* getting Transactions that you know that you should - > unless the Transactions within this Account happen to be the > first in the document with that particular IsCredit value > (which would generally only be for the first Account, I > imagine), you won't see them. > > Also, when you do: > > key('distinct', IsCredit) > > to get all the Transactions with the same IsCredit value, you get > *all* the Transactions, across the entire document, across > Accounts, with that particular IsCredit value. Which is why > you're getting Transactions in Accounts when you didn't want them. > > So that's the problem. One solution is to make the key > include some information about the identity of the Account in > which the Transaction's occurred, as well as the IsCredit > value. You need some unique identifier for each Account - I'm > guessing that the Account's Statement/Number acts as a unique > identifier; if all else fails you can use generate-id() to create one. > > Change the key to include the Account's identifier within the > key value, like so: > > <xsl:key name="distinct" match="Transaction" > use="concat(ancestor::Account/Statement/Number, '+', IsCredit)" /> > > Then to get the unique ones within the current Account > element, you can do: > > <xsl:variable name="account" select="Statement/Number" /> > <xsl:apply-templates > select="Transactions/Transaction > [count(. | key('distinct', > concat($account, '+', > IsCredit))[1]) = 1]"> > <xsl:sort select="IsCredit" order="descending" /> > </xsl:apply-templates> > > And to get all the rest of the Transactions with that > particular IsCredit within the Account of the current > Transaction, you can use: > > key('distinct', > concat(ancestor::Account/Statement/Number, '+', IsCredit)) > > --- > > In XSLT 2.0, because you don't use keys, these kinds of > scoping problems don't occur. You can simply do: > > <xsl:for-each-group select="Transactions/Transaction" > group-by="IsCredit"> > <xsl:sort select="IsCredit" order="descending" /> > ... > <xsl:for-each select="current-group()"> > ... > </xsl:for-each> > ... > </xsl:for-each-group> > > Does anyone else feel that an apply-templates-group > equivalent would be useful? I have a feeling that a lot of > people use a template, rather than a xsl:for-each, when > generating group-level output at the moment (certainly that's > what I've standardly done), which means changing things > around quite a lot when you start using XSLT 2.0 grouping > methods instead. > > Of course you can split things up by doing: > > <xsl:for-each-group select="Transactions/Transaction" > group-by="IsCredit"> > <xsl:sort select="IsCredit" order="descending" /> > <xsl:apply-templates select="." /> > </xsl:for-each-group> > > ... > > <xsl:template match="Transaction"> > ... > <xsl:for-each select="current-group()"> > ... > </xsl:for-each> > ... > </xsl:template> > > But the position() within the Transaction template is then > always 1, whereas with something like: > > <xsl:apply-templates-group select="Transactions/Transaction" > group-by="IsCredit"> > <xsl:sort select="IsCredit" order="descending" /> > </xsl:apply-templates-group> > > then the position() changes as you would expect. > > Cheers, > > Jeni > > --- > Jeni Tennison > http://www.jenitennison.com/ > XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Trouble with grouping, Jeni Tennison | Thread | RE: [xsl] CALS and keys (difficult), McNally, David |
[xsl] one node from multiple docs, Matt Lewis | Date | [xsl] or predicates, bernwardhanssen |
Month |