Subject: Re: [xsl] Trouble with grouping From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx> Date: Wed, 6 Feb 2002 10:22:40 +0000 |
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 -> |
---|---|---|
[xsl] Trouble with grouping, David B. Bitton | Thread | RE: [xsl] Trouble with grouping, David B. Bitton |
[xsl] Sorting Problem, Sachidanandam E K | Date | [xsl] Malformed META tag, Gautam Sabba |
Month |