xsl-list
[Top] [All Lists]

Re: [xsl] Streaming terminology: Climbing

2014-01-29 05:50:39
Yes, it's a very useful explanation.

I think your conceptual model that the processor is "positioned just after the 
start tag" is probably helpful to many people but it's worth pointing out that 
it's not in the spec and we try not to over-constrain implementations. There's 
also a glitch in it in that we (deliberately) define has-children() to be an 
inspection construct, and to evaluate this function the processor needs to peek 
just beyond the end of the start tag. (Saxon doesn't yet implement this).

There's also a minor error where you say:

A construct is climbing if, when executed, it yields the context node (self) or 
ancestors of the context node.

Apart from the fact that attribute selection is also climbing (despite the 
name), this confuses the role of the context node and the current streaming 
position. For example the construct

descendant::x/parent::y

is climbing, although it does not select ancestors of the context node. It's 
climbing because it reads information from the "stack" of ancestor data that is 
maintained as the streaming processor works its way through the document, and 
when you're positioned in that stack, your ability to select downwards is 
constrained.

Incidentally, at one time we defined the spec so that as well as retaining "the 
start tags of all ancestors" in this stack, we also retained some positional 
information about the position of each ancestor relative to its siblings, 
allowing match patterns such as match="para[1]". This has been dropped from the 
spec, but it's partially implemented in Saxon, and I have yet to decide whether 
to retain it in some form.

Michael Kay
Saxonica

On 29 Jan 2014, at 10:38, Costello, Roger L. <costello(_at_)mitre(_dot_)org> 
wrote:

Hi Folks,

Thanks to Abel's outstanding explanation, I created a few Powerpoint slides 
to explain "climbing":

http://www.xfront.com/XSLT-Streaming-Terminology-Climbing.pptx

Would you take a look at the slides and let me know of any inaccuracies 
please?

/Roger

-----Original Message-----
From: Abel Braaksma (Exselt) [mailto:abel(_at_)exselt(_dot_)net] 
Sent: Saturday, January 25, 2014 11:28 AM
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
Subject: Re: [xsl] Streaming terminology: Climbing

Hi Roger,

See comments between the lines.

Cheers,
Abel


On 24-1-2014 11:15, Costello, Roger L. wrote:
What nodes can a construct return in order for it to be considered a 
climbing construct?

This XPath expression 

     @*

returns all the attributes of the context node, so  @*  is a climbing 
construct, correct?

Yes, this is a climbing construct, even though it may feel as if you are
striding (moving sideways on the Title-element). Visited nodes,
including current namespace nodes and attributes are remembered by the
processor, but only for the ancestor-or-self axis. Once the Title
element is visited, the streaming processor has already processed all
its attributes and the read pointer is considered to be at the end of
the opening tag Title, hence the term "climbing".

This XPath expression 

     ancestor::*

returns all the ancestors of the context node, so  ancestor::*  is a 
climbing construct, correct?

Yes, it is a climbing construct. However, unless you select other
climbing nodes from here and unless you atomize the results (without
consuming the contents of the children) you can't do much with it.

This XPath expression 

     for $i in ancestor::node() return $i

also returns all the ancestors of the context node, so  for $i in 
ancestor::node() return $i  is a climbing construct, correct?

No, this is not a climbing construct, it is roaming and free-ranging.
The part in the middle, the expression ancestor::node() is climbing, but
you are not allowed to return the nodes from a for-in-return expression.
The return expression must be grounded for the whole construct to be
streamable. An example with a climbing construct in a for-expression
that is also streamable is:

for $i in ancestor::node() return string(@id)
for $i in somechild return $i/name()


This XPath expression 

     ../@*

returns all the attributes of the parent of the context node, so  ../@*  is 
a climbing construct, correct?

Yes, that is correct. But, just as in the previous example, be aware
that you cannot return this, because then navigating away from the node
would be possible at a later stage. Hence, you should typically use
expressions like this this in expressions that have operator usage
absorption or inspection, but not navigation.

This XPath expression 

     ./namespace::*

returns all the namespaces visible on the context node, so  ./namespace::*  
is a climbing construct, correct?

Correct.

Notice that all the examples are XPath expressions. Can you give an example 
or two of a climbing construct that is not an XPath expression?

Since every expression is an XPath expression, except for patterns (but
they inherit the syntax), the only other thing that can potentially be
climbing is a construct. Looking over the rules, it turns out that, if I
interpret them correctly, only a choice operand group can potentially be
climbing. There are two constructs that form a choice operand group. One
is an if-then-else expression (which is an XPath, so I don't consider it
an answer to your question), the other are the sequence constructors in
an xsl:choose construct. This turns out to be climbing, but only when
the tests are grounded and motionless. A simple example:

<xsl:choose>
   <xsl:when test="local-name(.) eq 'foo'">
      <xsl:sequence select="parent::bar" />
  </xsl:when>
  <xsl:otherwise>
     <xsl:sequence select="parent::foo" />
  </xsl:otherwise>
</xsl:choose>

In the above construct, the posture of each operand in the group is
climbing (as a result of the operand usage being transmission and the
use of the parent axis). The combined posture of the choice operand
group, however, is crawling. Also, since you are not allowed to return
streaming nodes, the xsl:sequence constructor should either be removed,
or the result should be wrapped in an xsl:value-of or something similar.

Other than that, I don't believe there is a construct that is climbing
and that doesn't visit nodes using any of the axis mentioned in the
climbing-description.


To recap:

     A construct is climbing if, when executed, it yields 
     the context node (self) or ancestors of the context node.
     Also a climbing construct can return attributes of
     the context node or attributes of ancestor nodes.
     Finally, a climbing construct can return namespaces
     that are visible on the context node or on any ancestor.

Is that correct?

Yes, it could. However, as you write here, because it "can return
nodes", and because streaming nodes cannot be moved around (because it
cannot statically be assessed what happens to them in a later
construct), this is not permitted in constructs such as xsl:with-param,
xsl:variable, xsl:apply-templates or as function arguments to stylesheet
functions (unless atomized).

Is there anything else important to know about understanding what a climbing 
construct is?

Probably a lot, but I think you got the essence wrapped up here.
Climbing constructs play an important role in path expressions and it is
important to understand that something like x/ancestor::y/z is not
allowed, because you are allowed to climb, but not allowed to descend
afterwards.


--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: 
<mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--



--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--


<Prev in Thread] Current Thread [Next in Thread>