Re: [xsl] Filtering sequences of atomic types

Subject: Re: [xsl] Filtering sequences of atomic types
From: "G. Ken Holman" <gkholman@xxxxxxxxxxxxxxxxxxxx>
Date: Thu, 27 Nov 2008 17:03:20 -0500
At 2008-11-27 20:31 +0000, Andrew Welch wrote:
> Or would this work even better for you:
>  <xsl:for-each select="//@xml:id[.=$string-sequence]">

It's possible (and preferable) to write that as:

<xsl:for-each select="id($string-sequence)">

isn't it?

Nope ... those aren't equivalent.

I've never used it but it worked in a quick sanity test I just did....
It's a bit like passing a sequence to key()

Sure it is, but your expression returns the element whose attribute is in the given sequence.

That may be what the original poster wanted, but what he asked for was the attribute itself whose value is in the given sequence... and I think my expression gives the original poster what they were asking for.

In fact we're both wrong, because he didn't ask for the attribute, he asked to filter an existing sequence of strings:

At 2008-11-26 21:33 +0100, Christoph LANGE wrote:
I'm trying to filter a sequence using a predicate that involves a node set.
What I actually want to do is something like

$string-sequence[. = //@xml:id]

Your expression returns an element ... my expression returned an attribute ... in order to get a sequence of strings I would first change my answer to be:


... which on third look still is incorrect because while it returns a sequence of strings it doesn't accommodate duplicates. Yes, there aren't supposed to be duplicates for xml:id= but that's only detected if the instance is validated. If the instance isn't validated then my answer would give duplicates if there were duplicate attributes.

So, to accommodate duplicates (as in, only have as many entries for a given string as is found in the sequence, not as found in the tree), I would have to withdraw my second answer and revert to my first answer, which is also the answer that Mike gave:

At 2008-11-26 15:45 -0500, I wrote:
You probably want something like:

  <xsl:variable name="tree" select="/"/>
  <xsl:for-each select="$string-sequence[.=$tree//@xml:id]">

... which, in fact, filters the string sequence without introducing any duplicates from the tree.

Since id() only returns the first if there are duplicates, this adaptation of yours would work:


... but *only* if there were no other attributes of type ID. If there are other attributes of type ID then your approach would include those in the return set if any of them were equal to a member of the sequence, rather than restrict the sequence to only those attributes *named* xml:id, which is what the original poster asked for.

Lots of nuances to think about! And it is a challenge during development to think of all the edge cases.

I hope this helps.

. . . . . . . . . Ken

Upcoming XSLT/XSL-FO, UBL and code list hands-on training classes:
:  Sydney, AU 2009-01/02; Brussels, BE 2009-03; Prague, CZ 2009-03
Training tools: Comprehensive interactive XSLT/XPath 1.0/2.0 video
Video sample lesson:
Video course overview:
G. Ken Holman                 mailto:gkholman@xxxxxxxxxxxxxxxxxxxx
Crane Softwrights Ltd.
Male Cancer Awareness Nov'07
Legal business disclaimers:

Current Thread