Re: [xsl] passing intermediate result while recursively building nodeset

Subject: Re: [xsl] passing intermediate result while recursively building nodeset
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Fri, 3 May 2002 16:10:51 +0100
Hi Paul,

> I have question which is a variation of a previous question I had
> ... I'd like to recursively build up a nodeset, and I'd like to pass
> the intermediate result on with each recursive call.

You could achieve what you're aiming for by creating a new result tree
fragment and converting that to a node set to pass on to the next
call. Something like:

<xsl:template name="myTemplate">
  <xsl:param name="nodes" select="/.." />
  <xsl:if test="count($nodes) < 5">
    <xsl:variable name="newNodes">
      <xsl:copy-of select="$nodes" />
      <a i="3" />
    <xsl:call-template name="myTemplate">
      <xsl:with-param name="nodes"
                      select="exsl:node-set($newNodes)/*" />

Obviously this one adds the same node each time and stops when it
reaches 5 nodes, but you get the general idea.

> Is this possible/reasonable/efficient?

It's possible, if you're using 1.1, 2.0 or an extension node-set()
function; otherwise it isn't, because when you create an element, then
it's in a result tree fragment which you can't treat in the same way
as a node.

I'm not sure if it's reasonable -- it really depends on what your goal
is, and you haven't described that.

This method isn't particularly efficient, because it involves a lot of
creation of new nodes. However your requirement for the new set of
nodes to be *ordered* means that I don't think you can avoid this, at
least in XSLT 1.0/1.1. (It might be that using the union operator
gives you what you want in a particular implementation -- it depends
on how the implementation orders nodes from different trees.)

> I was looking at the union operator, but it appears that there is no
> guarantee about the order of the elements in the resulting set and I
> would like to keep them ordered. If 1.1 can't handle this, will it
> be something that 2.0 will be able to do?

XPath 2.0 does away with "node sets" and replaces them by "sequences",
which of course do have an order. That makes this task a lot more
efficient because you don't have to re-copy the nodes that are passed
in each time. Instead, you can do:

<xsl:template name="myTemplate">
  <xsl:param name="nodes" select="/.." />
  <xsl:if test="count($nodes) < 5">
    <xsl:variable name="newNode">
      <a i="3" />
    <xsl:call-template name="myTemplate">
      <xsl:with-param name="nodes"
                      select="($nodes, $newNode/*)" />

The expression ($nodes, $newNode/*) creates a sequence that contains
all the nodes from $nodes followed by the element created within
the $newNode variable.



Jeni Tennison

 XSL-List info and archive:

Current Thread