[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

SUMMARY: Selecting unique value of an attribute


Subject: SUMMARY: Selecting unique value of an attribute
From: Paul Terray <terray@xxxxxxxxxxxx>
Date: Wed, 23 Aug 2000 19:24:52 +0100

OK, time for summary.

The problem is the one of doing an index from entries in the text. You want a list where word do not repeat themselves. The example here use empty tags with entry as attributes, but you can do with the same algorithms if you use enclosing tags.

First, My little XML snippet :
<text>
<index entry="thing"/> blablabla <index entry="stuff"/> blabla <index entry="this"/>
bliblabla<index entry="thing"/> bla bli bla<index entry="this"/> bli <index entry="stuff"/>
<index entry="thing"/>and bla and bli <index entry="stuff"/>
</text>


I want to get a list with :
-stuff
-thing
-this

There is about two ways of doing it :

- One using the comparison with the preceding element in a sorted subtree, with a sub-template. This give a solution like this :
"Robert Stupak" <robert@xxxxxxxxxxx>
  <xsl:template match="text">
    <xsl:apply-templates select="index">
        <xsl:sort select="@entry"/>
    </xsl:apply-templates>
  </xsl:template>


<xsl:template match="index"> <xsl:if test="not(@entry = preceding::index/@entry)"> <xsl:value-of select="@entry"/> </xsl:if> </xsl:template>

This solution is clean to read, although I do prefer the other one for compacity and probably performance.


- The other solution is more complicated to understand. By using a key, you group all identical entries, and take only the first of them, like this :
Oliver Becker <obecker@xxxxxxxxxxxxxxxxxxxxxxx>
Something like this:
Define a key for every @entry of index:
<xsl:key name="paul" match="index" use="@entry" />

Then walk through your index elements and choose only the first of
each group (i.e. each key)
<xsl:for-each select="index[generate-id()=generate-id(key('paul',@entry)[1])]">


now you have unique entries which need to be sorted:
<xsl:sort select="@entry" />

Ok - here you are! Output, and that's all:
<xsl:value-of select="@entry" />


The complete template is <xsl:template match="paul"> <xsl:for-each select="index[generate-id()=generate-id(key('paul',@entry)[1])]"> <xsl:sort select="@entry" /> <xsl:value-of select="@entry" /> <xsl:text>&#xA;</xsl:text> </xsl:for-each> </xsl:template>

I like that one, because it is rather subtile, and allow me to do a multiple level index easily.


Another advantage is how easy it is to make hypertext entry beside (you need one per element in the xml).

However, it is a question of taste and I don't see how one is better than the other.

Thanks for everybody who answered (including Miloslav Nic, whose first answer was good enough for me :-)
--
Paul Terray - terray@xxxxxxxxxxxx
tel : 01 34 58 70 76




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



Current Thread
Keywords
xml