Subject: Re: [xsl] multi-level grouping trouble From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx> Date: Mon, 2 Apr 2001 08:34:32 +0100 |
Hi Dave, > Yes, I've looked at Jeni's example message on multi-level grouping. > I'm still having trouble with this, though, and would appreciate if > someone could point out what I'm still doing incorrectly. I think > that the first-level grouping is okay, but that the second-level is > hosed. Take a look at how you're calling the second level grouping. You've set up the key as: > <xsl:key > name="i_by_su" > match="i" > use="concat(s,' ',u)"/> Then you're using it here: > <xsl:template match="i"> > <tr><td><h3><xsl:value-of select="s"/></h3></td></tr> > <xsl:for-each select="s[generate-id(u) = > generate-id(key('i_by_su',u)[1])]"> > <xsl:sort select="b"/> > <xsl:sort select="e"/> > <xsl:apply-templates select="."/> > </xsl:for-each> > </xsl:template> So what you're saying in that second line is: for each s element where the unique ID of its child u element is equal to the unique ID of the first (i element) returned by calling the 'i_by_su' key with a key value being the value of the (s element's) u child That's a little bit astray. You're actually after *i elements* (again). And you want the *i elements* whose own unique ID is the same as the first i element returned from the key when you access it with a key value being the composite s concatenated with u (with a space separator). i[generate-id(.) = generate-id(key('i_by_su', concat(s, ' ', u))[1])] Note that this is exactly the same as the one for the one-level key, except that the key name and key value have changed to match the key name and key value that you've set up. Now, one issue is how to get those i elements. You're in an 'i'-matching template so an 'i' element is the current node. You could do simply: ../i[generate-id(.) = generate-id(key('i_by_su', concat(s, ' ', u))[1])] But that means that the processor will work through *all* the i elements to find those whose unique ID matches the first from the key. You don't want that because you only want those who have the same 's' as the current i element. So you can use the 'i_by_s' key to get those, before filtering them to find those that are unique in the second group: key('i_by_s', s)[generate-id() = generate-id(key('i_by_su', concat(s, ' ', u))[1])] You actually get very close to this in the s-matching template. Note that if you just change the select expression of the xsl:for-each in the i-matching template to the above, then you'll be in trouble because you're applying templates to the current node within the xsl:for-each, which will apply templates to an 'i' element, which matches the same template and does the same thing again. If you want to iterate over the s elements next, then just select the s element children of the i elements: key('i_by_s', s)[generate-id() = generate-id(key('i_by_su', concat(s, ' ', u))[1])]/s Or you could apply templates to the i elements in a different mode. That's what I would usually do. Whichever you do, you can then use the key in its plain form to get *all* the i elements with a particular s and u. For example, in an i-matching template, you can get all the i elements with the same s and u as the current i element with: key('i_by_su', concat(s, ' ', u)) One more thing - is there any reason that you're wrapping an xsl:for-each around an xsl:apply-templates like this: <xsl:for-each select="i[generate-id(.) = generate-id(key('i_by_s',s)[1])]"> <xsl:sort select="s"/> <xsl:apply-templates select="."/> </xsl:for-each> That's almost exactly the same as just: <xsl:apply-templates select="i[generate-id() = generate-id(key('i_by_s', s)[1])]"> <xsl:sort select="s" /> </xsl:apply-templates> The latter is not only shorter, but (if it's important) the position() of the i elements within the i-matching template will reflect the order in which they're processsed, rather than always being 1. > I am willing to use saxon:intersection, since I'm already using > saxon:preview just to be able to create the input data in the first > place. Well you may want to use saxon:hasSameNodes() rather than using generate-id() to test node equality. For example: i[saxon:hasSameNodes(., key('i_by_s', s)[1])] I hope that helps, 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] multi-level grouping trouble, Dave Gomboc | Thread | thanks Re: [xsl] multi-level groupi, Dave Gomboc |
[xsl] multi-level grouping trouble, Dave Gomboc | Date | Re: [xsl] XSL Namespaces - confused, David Carlisle |
Month |