Re: Nodes between two nodes with same name

Subject: Re: Nodes between two nodes with same name
From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx>
Date: Sat, 19 Aug 2000 11:22:53 +0100
Jonas,

>What I need is to select nodesets including nodes <tag> and
>all other till next <tag> node.

With any grouping question like this, there are two stages: identify the
first nodes in the group, and identify the rest of the nodes in the group
from that first one.

In your case it's easy to identify the first node in the group: they're the
tag elements.  So, if you just process the 'tag' elements, then you can
process the rest of the elements you want within that template:

<xsl:template match="body">
  <xsl:apply-templates select="tag" />
</xsl:template>

<xsl:template match="tag">
  ...
</xsl:template>

It's identifying the rest of the nodes that's the difficulty.  So what is
it that identifies the group?  You want all the nodes that are before the
next tag in the list.  So, for all the nodes in the group, the next 'tag'
element is going to be the same element.

You can get the 'next tag element' with the XPath:

  following-sibling::tag[1]

And you can get the next elements (of any kind) with the XPath:

  following-sibling::*

Now you want a predicate that can select, from all those elements, those
elements whose next 'tag' element is the same as the next 'tag' element for
the current 'tag' element.  Within the 'tag' template, the 'tag' element is
the current node, so the *next* tag element can always be identified with:

  current()/following-sibling::tag[1]

And comparing nodes can be done with generate-id(), giving us the final XPath:

  following-sibling::*[generate-id(following-sibling::tag[1]) = 
                       generate-id(current()/following-sibling::tag[1])]

So here is a template that groups your input just by putting each of the
groups (separated by the 'tag' elements) inside 'group' elements:

<xsl:template match="tag">
 <group>
   <xsl:copy-of select="
   following-sibling::*[generate-id(following-sibling::tag[1]) = 
                        generate-id(current()/following-sibling::tag[1])]
       " />
  </group>
</xsl:template>

This works in SAXON and Xalan.

I hope that this helps,

Jeni

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


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


Current Thread