result tree fragement, node-set difference

Node-set

1. node-set vs Result tree fragment?
2. nodeset A contains nodeset B

1.

node-set vs Result tree fragment?

David Carlisle



> Is there somewhere I can find an example of the difference between a 
> node set and a result tree fragment?

archives of this list, xslt spec.


> Is a node set just a "path",

No a path is an expression (think x + 3 in C or fortran etc) a node set is a value (think 5 in c or fortran) in common with most other languages variables in xslt can only hold values not expressions.

A result tree fragment could have been the same as a node set (and is in xslt2 drafts) but in xslt 1 there is a restriction that stops you making queries, further transforms on the result of a transformation. If you use a variable binding element (xsl:variable xsl:param or xsl:with-param with content rather than a select expression teh result of executing the content is stored in the variable as a result tree fragment, the only thing you can do with that is copy it to the final result using xsl:copy-of or convert it to a string (just about any other operation on it) in partiular you can not use an Xpath / step to go $x/a/b/c to extract the element nodes out of the variable.


> Is a node set just a "path", or set of nodes with only one
"destination"

a node set is a set of nodes, I'm not sure what you mean by destination.

Joerg Pietschmann offers

A node set is a set of nodes grabbed from the a source tree, either the original input, returned by document(), or constructed with an XPath extension function which returns a node set.

A result tree fragment (RTF) is a tree constructed in a style sheet variable. If you use xsl:variable without the select attribute, you are always creating a RTF. RTFs can only be created in stylesheet variables.

This puts a node set into the variable

   <xsl:variable name="foo" select="/foo"/>

This variable holds a string:

   <xsl:variable name="foo" select="'/foo'"/>

This constructs a RTF. It holds a text node as the single child of the root node of the RTF. The root node of a RTF is similar to the root node of a source tree


   <xsl:variable name="foo">/foo</xsl:variable> 

While dereferencing this variable gets the same value as for the variable above in all useful situations, they are different.

This constructs a RTF too. It contains eleent nodes as the children of the root node:

   <xsl:variable name="foo">
     <xsl:copy-of select="/foo"/>
   </xsl:variable>

If you now think the distinction between a node set and a RTF is silly, then you may have a point. The spec authors thought treating RTFs the same as source trees might prove difficult and/or prevent optimizations, and they decided to play safe: A RTF can only be copied into the result tree or used via string conversion in an XPath expression, which means you can't select nodes from them.

The following expression will always be valid, regardless which of the for forms above is used.

  concat($foo,'/bar')

If the source xml was

  <foo>/foo</foo>

the result is always the same, the string "/foo/bar".


> Is a node set just a "path", or set of nodes with only one "destination"
> node vs. a result tree that gives multiple node sets?

I don't understand the question. Some XSLT statements require the XPath expression in the select attribute to evaluate into a node set. I'm not sure what you count as "a path", the expression (/foo|$foo/bar|document('foo.xml')) ought to evaluate in a node set too, provided $foo holds a node set.

2.

nodeset A contains nodeset B

Wendell Piez



>As for using a node set as a kind of array and checking for the
>existence of the desired substring in the text value of each node (in
>this case, the equivalent of an array element), you need a mechanism
>to cicle through all the nodes in the node set (all the "elements" in
>the "array"). Otherwise, only the first node will be checked.

Given a nodeset, in simpler cases one can ask for

$nodeset[contains(.,$string)]

to return any (all) members of $nodeset that contain a substring $string. This subset coerces to Boolean true when it has any members, so one can say

<xsl:when test="$nodeset[contains(.,$string)]">...</xsl:when>

and get the desired behavior. (And indeed one can inspect this subset to see what members it has, etc.)

In more complex cases one has to resort to recursion. Because it is so cumbersome, however (relatively), and because simple string equivalence testing is so easy, another approach is simply to design around this problem. As Mike pointed out,

$nodesetA = $stringB

if *any* node in $nodesetA has string value $stringB.

Ordinarily I don't recommend "designing around problems", but conversely, it's also true that a good design is good precisely because it tends to avoid such problems. XSLT 1.0 was not built to support arbitrary queries over XML or even arbitrary transformations

If confined to XSLT 1.0, one conceivable solution, accordingly, is to preprocess your input in such a way that the values you are looking for are normalized as single strings, and substring analysis (not the language's strength) is therefore avoided.

Another approach is to look to Dimitre's work with FXSL, which by taking advantage of quasi-functional features in XSLT (when it is permitted to process its own results with an extension function in 1.0) abstracts many such problems away, at the cost of mastering its concepts.