Re: [xsl] XPath question concerning distinct-values()

Subject: Re: [xsl] XPath question concerning distinct-values()
From: Mukul Gandhi <gandhi.mukul@xxxxxxxxx>
Date: Wed, 8 Aug 2012 19:32:16 +0530
Hi Thorsten,
    I agree, that the approach suggested by Mike is the most elegant
from all the approaches suggested in this thread.

The subject line of your post mentioned, "XPath question concerning
distinct-values()", which probably made many of us think that use of
distinct-values() function was needed in the solution you were
seeking. But that is fine, since de-duplicating of data (which
distinct-values() does) was needed to solve this use case. As evident
in Mike's solution, the for-each-group internally does de-duplicating
on a "key field" and builds the groups keyed by the "key field".

You've cited <xsl:key> from my solution. The XSLT "key" construct,
builds a kind of in-memory index (identified by the "match" and "use"
attributes of <xsl:key>). Later in an XSLT stylesheet, when we use the
"key()" function to lookup (for a specific value of the "key") the
index built by <xsl:key>, they key() function returns the matching
nodes from an XML instance document. This is an efficient way to look
up data (the difference may be significant, for large amounts of data)
from XML instance documents. The other approach I suggested, did a
manual lookup of data by an XPath expression.


On Wed, Aug 8, 2012 at 2:06 PM, Thorsten <xsl-list@xxxxxxxxxxxxx> wrote:
> Hello Michael,
> hello Mukul,
>
> I've used Michael's suggestion, cause it seems to be the simplest way to do
> this, as he wrote too.
>
> Michael Kay <mike@xxxxxxxxxxxx> hat am 3. August 2012 um 15:20 geschrieben:>
> It's simplest to use xsl:for-each-group for this.
>>
>> <xsl:template match="pricelist">
>> <xsl:for-each-group select="item" group-by="order-number">
>> <xsl:value-of select="current-group()[1]/(order-number, price),
>> '&#xa;'"/>
>> </xsl:for-each-group>
>> </xsl:template>
>>
>>
>> Michael Kay
>> Saxonica
>>
>
> Mukul, your solutions are really interessting! Thank you too. Maybe I can use
> something like that somewhen!
> (Well, never ever used <xsl:key> before...)
>
>
> Mukul Gandhi <gandhi.mukul@xxxxxxxxx> hat am 3. August 2012 um 18:01
> geschrieben:> Hi Thorsten,
>> Here are few more 2.0 approaches (hopefully, would meet your
>> requirement) to solve this problem:
>>
>> 1)
>>
>> <xsl:template match="/">
>> <xsl:variable name="unique-order-nums"
>> select="distinct-values(pricelist/item/order-number)"/>
>> <xsl:variable name="docRoot" select="/"/>
>> <xsl:for-each select="$unique-order-nums">
>> <xsl:value-of select="current()"/><xsl:text>
>> </xsl:text><xsl:value-of select="$docRoot/pricelist/item[order-number
>> = current()][1]/price"/><xsl:text>&#xA;</xsl:text>
>> </xsl:for-each>
>> </xsl:template>
>>
>>
>> 2)
>>
>> <xsl:key name="item-key" match="item" use="order-number"/>
>>
>> <xsl:template match="/">
>> <xsl:variable name="unique-order-nums"
>> select="distinct-values(pricelist/item/order-number)"/>
>> <xsl:variable name="docRoot" select="/"/>
>> <xsl:for-each select="$unique-order-nums">
>> <xsl:value-of select="current()"/><xsl:text>
>> </xsl:text><xsl:value-of select="key('item-key', current(),
>> $docRoot)[1]/price"/><xsl:text>&#xA;</xsl:text>
>> </xsl:for-each>
>> </xsl:template>





-- 
Regards,
Mukul Gandhi

Current Thread