Re: [xsl] getting a unique list using substring-after()

Subject: Re: [xsl] getting a unique list using substring-after()
From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx>
Date: Sat, 3 Feb 2001 11:52:21 +0000
Hi Aedemar,

> can anyone explain why using the substring-after function
> <xsl:variable name = "unique-resources"
> select="//navigation_page/navigation/related/content/resource[not(substring-
> after(@id,'-')=substring-after(preceding-sibling::resource/@id,'-'))]"></xsl
> yields
[repeated entries]

If you pass a node set as the first argument of the substring-after
function (and lots of other functions too), then it only uses the
string value of the *first* of these (in document order). So:

  substring-after(preceding-sibling::resource/@id, '-')

will *always* give the same result for any resource set - the text
after the '-' in the first resource element's id attribute.  Most of
the resources in your file don't match this value, so you get all
those repeated entries.

If the unique resources are stored in this way, and you're using this
method to discover the unique resources, then you can't put them in a
variable (well, I guess you could if you were prepared to use a
node-set() extension function).  Instead you should need to wrap
whatever you're doing to the unique resources within an xsl:for-each
with an internal xsl:if:

   <xsl:if test="preceding-sibling::resource
                    [substring-after(@id, '-') =
                     substring-after(current()/@id, '-')]">
      <!-- do whatever you do with the unique resources -->

I'm not sure what your input looks like, but often it's more efficient
to use the Muenchian Method to identify unique nodes.  This involves
defining a key that allows you to quickly find all the nodes with the
same value for whatever property you're using to distinguish between
them.  The match pattern should match the nodes you're interested in,
and the use expression should show how to work out the unique value
for the node:

<xsl:key name="resources" match="resource"
         use="substring-after(@id, '-')" />

With that key defined, then you may be able to use:

<xsl:variable name="unique_resources"
             [count(.|key('resources', substring-after(@id, '-'))[1]) = 1]" />

This might not give exactly what you want if you're actually uses
something about the context of the resource element (e.g. which
content element it's in) to find the unique resources, but I don't
think that you are.

I hope that helps,


Jeni Tennison

 XSL-List info and archive:

Current Thread