Re: [xsl] XSLT: XPath: Sets

Subject: Re: [xsl] XSLT: XPath: Sets
From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx>
Date: Tue, 27 Feb 2001 17:55:03 +0000
Hi Lee,

> Is it possible to apply one template to every first-level node
> (/ROOT/*) in a document and have the template output a mark if the
> passed node is the first of its kind? So that in the example below,
> <X a="1"/> would be marked but not <X a="2"/>?

You can test whether a node is the first with that name within its
siblings by seeing if there are any preceding siblings to it that have
the same name, i.e.:

  preceding-sibling::*[name() = name(current())]

So you could do something along the lines of:

<xsl:template match="/*/*">
   <xsl:choose>
      <xsl:when test="preceding-sibling::*[name() = name(current())]">
         ... first of its kind ...
      </xsl:when>
      <xsl:otherwise>
         ... later elements ...
      </xsl:otherwise>
   </xsl:choose>
</xsl:template>

If you've got a long document you may find it more efficient to create
a key so that you can quickly retrieve all the elements with a
particular name:

<xsl:key name="elements-by-name" match="/*/*" use="name()" />

You can then test whether the current node is the first with a name
with:

  count(.|key('elements-by-name', name())[1]) = 1

or:

  generate-id() = generate-id(key('elements-by-name', name()))

These both test whether the current element is the first element
returned by the key for that particular key value (the name of the
element).

I hope that helps,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/



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


Current Thread