[XSL-LIST Mailing List Archive Home]
[By Thread]
[By Date]
Bob,
The simple solution would just be
<xsl:template match="factor">
<xsl:for-each select="components/component[not(.=preceding-sibling::component)]">
<xsl:value-of select="."> ... etc ...
But maybe you're looking at more than that? This won't work if the components you wish to deduplicate aren't siblings of one another. Nor is the preceding:: axis much help, if you're trying to use keys.
Because you want to punctuate your deduplicated list, a more general solution hits up against the limitations of the one-pass limitation in XSLT 1.0. (This is because your collection of the deduplicated nodes has to occur within a single XPath if you want to punctuate it properly.) This means in 1.0 you're probably going to have to use a compound key (key the components to a concatenation of their value with a generated id for their group ancestor) and deduplicate from that set.
Or, if using 2.0, grouping constructs can be used to deduplicate:
XSLT 2.0 makes this kind of thing much easier.
Or, in 1.0, do two passes....
At 02:46 PM 9/14/2006, you wrote:
Re: [xsl] Re: Ignoring Duplicates In key()
Subject: Re: [xsl] Re: Ignoring Duplicates In key() From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx> Date: Thu, 14 Sep 2006 18:03:09 -0400 |
Bob,
The simple solution would just be
<xsl:template match="factor">
<xsl:for-each select="components/component[not(.=preceding-sibling::component)]">
<xsl:value-of select="."> ... etc ...
But maybe you're looking at more than that? This won't work if the components you wish to deduplicate aren't siblings of one another. Nor is the preceding:: axis much help, if you're trying to use keys.
Because you want to punctuate your deduplicated list, a more general solution hits up against the limitations of the one-pass limitation in XSLT 1.0. (This is because your collection of the deduplicated nodes has to occur within a single XPath if you want to punctuate it properly.) This means in 1.0 you're probably going to have to use a compound key (key the components to a concatenation of their value with a generated id for their group ancestor) and deduplicate from that set.
Or, if using 2.0, grouping constructs can be used to deduplicate:
<xsl:template match="factor"> <xsl:for-each-group select=".//component" group-by="."> <xsl:value-of select="current-group()[1]"/> <!-- or use current-grouping-key() --> <xsl:if test="not(position()=last())">, </xsl:if> </xsl:for-each> </xsl:template>
XSLT 2.0 makes this kind of thing much easier.
Or, in 1.0, do two passes....
Cheers, Wendell
At 02:46 PM 9/14/2006, you wrote:
Whoops, spoke too soon. That gives a similar result when applied to the original XSLT. More specifically, creating a new key
<xsl:key name="ComponentByValue" match="component" use="." />
<xsl:for-each select="key('ComponentByGroup',$group)"> <xsl:sort select="."/> <xsl:if test="generate-id(.) = generate-id(key('ComponentByValue',.)[1])">
Still only generates ", gewgaw".
Rats!
Still here, Bob Portnell simply.bobp@xxxxxxxxx
On 9/14/06, Bob Portnell <simply.bobp@xxxxxxxxx> wrote:Hmm. Okay, answer found: http://www.biglist.com/lists/xsl-list/archives/200006/msg00748.html
Sorry for the distraction. BobP
On 9/14/06, Bob Portnell <simply.bobp@xxxxxxxxx> wrote: > Here's some fun in XSLT 1.0, using variously the MSXML 3.0 or xsltproc > processors (result behaviors are the same). > > Here's some data... > > <factor group="0" > > <number>100</number> > <components> > <component>widget</component> > </components> > </factor> > <factor group="1"> > <number>110</number> > <components> > <component>widget</component> > <component>gewgaw</component> > </components> > </factor> > <factor group="1"> > <number>112</number> > <components> > <component>gewgaw</component> > </components> > </factor> > > My need is to create a string of unique "components" in a "group". The > original XSLT for this relied on a recursion structure and wasn't > successfully blocking duplicates. My notion was to just wait for it to > finish all the recursion (for its other needs), and then hit it with a > key(), defined thus: > > (XSLT fragment) > > <xsl:key name="ComponentByGroup" match="component" use="../../@group" /> > > (and then) > > <xsl:variable name="ComponentString"> > <xsl:for-each > select="key('ComponentByGroup',$group)[not(.=preceding::component)]"> > <xsl:sort select="."/> > <xsl:if test="position() > 1"> > <xsl:text>, </xsl:text> > </xsl:if> > <xsl:value-of select="." /> > </xsl:for-each> > </xsl:variable> > > The desired output would be "gewgaw, widget", but for some reason I'm > getting only "widget." When applied to more complex data, in one case > where 12 items should be displayed, it's correctly stopping the > duplicates but also making two singletons vanish. > > The [not(.=preceding::component)] is the basic structure I found for > reducing duplicates, but it doesn't seem to play quite nicely with the > key() ... it's reducing too many! > > Thoughts welcome. > > Bob Portnell > simply.bobp@xxxxxxxxx
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
[xsl] Re: Ignoring Duplicates In ke, Bob Portnell | Thread | Re: [xsl] Re: Ignoring Duplicates I, Bob Portnell |
[xsl] What's an ID?, Wolfgang Jeltsch | Date | Re: [xsl] What's an ID?, Wendell Piez |
Month |