[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: Stuck with select distinct

Subject: Re: Stuck with select distinct
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
Date: Mon, 10 Nov 2008 15:52:13 -0500
Re:  Stuck with select distinct

One can frequently use raw XPath to achieve the same end as using a key. It's just that for certain applications in certain processors, this can give very poor performance.

In order to get all 'colour' values, as you know, you can traverse "//colour".

In order to exclude Red and Blue, use a predicate:

//colour[not(.='Red' or 'Blue')]

You have also stipulated that "rgb value is not FFFFFF". But 'colour' sometimes has several 'rgb' element siblings. Your source code sample suggests it's the 'rgb' value directly following each 'colour' that is a concern, so:

//colour[not(.='Red' or 'Blue')][not(following-sibling::rgb[1]='FFFFFF']

which returns all colour elements whose value is not 'Red' or 'Blue' and whose directly succeeding 'rgb' element's value is not 'FFFFFF'.

To pull the distinct values from this set without a key, the easiest thing is to perform a test within your for-each (or your matched template), as in

<xsl:for-each select="$colours">
  <xsl:variable name="pos" select="position()"/>
  <xsl:if test="not(. = $colours[position &lt; $pos])">

... which is very direct and useful for many purposes.

Not for all, however. (For example, if positions are going to be important within the for-each.) Then you have to filter $colours itself to keep only distinct values, which means brute-force testing using the predicates again:

$colours[not(. = preceding::colour[not(.='Red' or 'Blue')]

... which is so outlandish (and potentially so poor in performance) that one wonders why you'd "prefer to avoid using keys if possible", since a key is so straightforward:

<xsl:key name="c" use="."
  match="colour[not(.='Red' or 'Blue')]

and then select="$colours[generate-id()=generate-id(key('c',.)[1])]"/>


At 11:36 AM 11/8/2008, you wrote:
Hi All

I'm trying to get a list of distinct items from an XML. I've done this many times using a predicate containing a preceding axis, but this one has got me stumped:


I need to return a nodeset with a list of DISTINCT colour nodes, that I can then process in a for-each element.

The other conditions for selection are:

    colour is not Red or Blue
    rgb value is not FFFFFF

I somehow need to combine the following predicates (I think)

    colours/colour[. != 'Red' and . != 'Blue']
    colours/rgb[. != 'FFFFFF']
    colours/colour[not(. = preceding-sibling::colour)]

I'm stuck with XSL 1.0 and would like to avoid using keys if possible

Any suggestions greatly appreciated



Wendell Piez                            mailto:wapiez@xxxxxxxxxxxxxxxx
Mulberry Technologies, Inc.                http://www.mulberrytech.com
17 West Jefferson Street                    Direct Phone: 301/315-9635
Suite 207                                          Phone: 301/315-9631
Rockville, MD  20850                                 Fax: 301/315-8285
  Mulberry Technologies: A Consultancy Specializing in SGML and XML

Current Thread


Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
First Name
Last Name
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.