Re: [xsl] find Unique Nodes based on 2 Attributes

Subject: Re: [xsl] find Unique Nodes based on 2 Attributes
From: Joerg Pietschmann <joerg.pietschmann@xxxxxx>
Date: Tue, 23 Oct 2001 09:31:48 +0200
"cutlass" <cutlass@xxxxxxxxxxx> wrote
> why not use an 'and' to connect 2 tests together ?

for the problem:

> From: "Damian Mcbride" <damian.mcbride@xxxxxxxx>
> > I can select a unique node when it is based on one attribute value, but
> when
> > I try to do this with two attribute values I run in to trouble.
> > Example XML
> > <Alert>
> > <Subscriber phonenumber="001" language="fr" alertmethod="SMS"/>
> > <Subscriber phonenumber="002" language="en" alertmethod="SMS"/>
> > <Subscriber phonenumber="003" language="en" alertmethod="SMS"/>
> > <Subscriber phonenumber="004" language="de" alertmethod="email"/>
> > <Subscriber phonenumber="005" language="It" alertmethod="NokiaSmart"/>
> > <Subscriber phonenumber="006" language="It" alertmethod="NokiaSmart"/>
> > <Subscriber phonenumber="007" language="de" alertmethod="NokiaSmart"/>
> > <Subscriber phonenumber="008" language="de" alertmethod="SMS"/>
> > </Alert>

Well, as Mr.Kay already noted, the simple aproach may not work.
In detail, the statement
  select="Subscriber[    not(@language=following::Subscriber/@language)
                     and not(@alertmethod=following::Subscriber/@alertmethod)]"
can be reformulated as follows:
  select Subscriber
  where    there is not any following subscriber with the same language attribute
       and there is not any following subscriber with the same alertmethod attribute

This means, the first element from the following set 
  <Subscriber language="It" alertmethod="NokiaSmart"/>
  <Subscriber language="It" alertmethod="SMS"/>
  <Subscriber language="de" alertmethod="NokiaSmart"/>
will not be selected, as there is both an element with the same
language and (another) element with the same alertmethod. The original
poster probably wanted to filter out elements which have the same
language and alertmethod at the same time.
The statement
  select="Subscriber[not(    @language=following::Subscriber/@language
                         and @alertmethod=following::Subscriber/@alertmethod)]"
wont work either for similar reasons.
Mr.Kay gave the usual but somewhat terse hint to use Munchean Grouping.
The key to this technique is to use xsl:key. In this case it has to
be a compound key using the concat() function:
  <xsl:key name="Subscriber-by-attr" match="Subscriber" 
           use="concat(@language,':',@alertmethod)"/>

The key will select all elements with the same pair of language
and alertmethod attributes. In order to get the pairs actually
contained in the document, we select all Subscribers, but attach a
condition that only the Subscriber which is the same as the first
node in the set of nodes with the same language/alertmethod pair
as selected by the key:
  select="Subscriber[generate-id()=generate-id(key('Subscriber-by-attr',concat(@language,':',@alertmethod))[1])]"

HTH
J.Pietschmann

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread