Re: [xsl] Content constructors and sequences

Subject: Re: [xsl] Content constructors and sequences
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Wed, 9 Jan 2002 15:34:21 +0000
[Resent as this doesn't appear to have come through...]

Hi Mike,

> On the question of "rootless nodes", (more correctly, "documentless
> nodes"), I have concerns about mutability. If a variable $v
> references such a node, then when the node is added to a document,
> the value of count($v/ancestor::*) is going to change. This suggests
> we are going to get into problems of defining sequential order of
> execution. Similarly, adding a node to a document is likely to
> change its position in document order relative to other nodes, which
> means that sequences that were in document order are no longer in
> document order. My worries may be misplaced (the data model suggests
> that when a node is added to a tree, you logically create a copy),
> but I didn't want to support rootless nodes in XSLT until we were
> confident that there were no nasties in this area (or until we could
> identify any benefits).

I think I see what you're getting at. If you had:

  <xsl:variable name="numbers" type="element number*">
    <xsl:for-each select="(1, 2)">
      <number><xsl:value-of select="." /></number>
    </xsl:for-each>
  </xsl:variable>

Then the $numbers variable would essentially hold (apologies for the
mish-mash syntax):

  (<number>1</number>, <number>2</number>)

And both number elements would be documentless nodes (I used
'rootless' as that's the terminology in the WD, BTW).

If you then did (assuming the suggested backwards compatability rules
for variable-binding elements):

  <xsl:variable name="doc1">
    <xsl:for-each select="$numbers">
      <xsl:item select="." type="element number" />
    </xsl:for-each>
  </xsl:variable>

  <xsl:variable name="doc2">
    <xsl:for-each select="$numbers">
      <xsl:item select="." type="element number" />
    </xsl:for-each>
  </xsl:variable>

then according to the result tree construction rules that I described,
both $doc1 and $doc2 would be document nodes (different ones), with
the *same* identity. In other words:

  $doc1/number == $doc2/number

would be true. But nodes can only have one parent.

I think that you can bypass this problem by stating that documentless
nodes are added to a document by creating a deep copy. If you said
that, then:

  $doc1/number == $doc2/number

would be false. Also:

  $numbers[1] == $doc1/number
  $numbers[2] == $doc2/number

would both be false.

I don't know whether this would impractical performance-wise
(conceptually, there are at least two copies of every new node you
generate). Presumably it would be fairly trivial to identify cases
where a new node could be 'reused' and those where it could not?

Another alternative is to make it an error to evaluate an xsl:item
element within a sequence constructor when the result sequence will be
used to create (part of) a result tree. This would also get around the
problem of what to do when simple typed values and pre-existing nodes
are included in such a sequence. Some situations could be tested for
statically (no xsl:item as a descendant of xsl:element, no xsl:item as
a descendant of an xsl:variable without a type attribute [except, in
both cases, if it appears within another xsl:variable element that
*does* have a type attribute]).

So I don't think it's insurmountable.

> You might be interested that one of the reasons that XSLT 1.1 was
> pulled was because some members of the WG had this kind of
> processing model in mind, and saw that it could create backwards
> compatibility problems with the RTF=nodeset issue. (For all I know,
> it was because James Clark was thinking this way that the RTF
> restrictions were present in XSLT 1.0 in the first place...)

Certainly getting a tree, rather than a sequence from a variable is
very useful. In particular:

 - it's easier to do $foo/element rather than $foo[self::element]
 - it's a lot easier to navigate between siblings in a document than
   between preceding/following items in a sequence

You can make xsl:variable work in this way, even if it's set to a
sequence, if you use a wrapper element. However, I guess there's an
argument that an explicit xsl:document to create a document node would
be a neater approach...

Anyway, thanks very much for your comments - I'll edit the section on
rootless/documentless nodes and creating result trees in light of the
above.

Cheers,

Jeni

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


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


Current Thread