RE: Traverse order

Subject: RE: Traverse order
From: Mike Brown <mbrown@xxxxxxxxxxxxx>
Date: Tue, 17 Aug 1999 15:35:32 -0600
> When the XSL processor processes the XML document, it will 
> read the root element first, then the child elements.
> Can we construct an XSL stylesheet to do the post-order
> traverse, it print out the leaf element which has no
> child, then the parents, and the last one is the root
> element.

Thank you for reposting this question with a new subject line. I do not have
"the answer" but I can point you to some relevant portions of the working
drafts:

1. What are child elements?

http://www.w3.org/TR/xpath#element-nodes

"The children of an element node are the element nodes, comment nodes,
processing instruction nodes and text nodes for its content [...] The
descendants of an element node are the children of the element node and the
descendants of the element children nodes."


2a. How does an XSLT processor normally handle elements or the root node?

http://www.w3.org/TR/WD-xslt#built-in-rule

<xsl:template match="*|/">
  <xsl:apply-templates/>
</xsl:template>


2b. What does <xsl:apply-templates/> do?

http://www.w3.org/TR/WD-xslt#section-Applying-Template-Rules

"In the absence of a select attribute, the xsl:apply-templates instruction
processes all of the children of the current node, including text nodes."
[...] "A select attribute can be used to process nodes selected by an
expression instead of all children. The value of the select attribute is an
expression. The expression must evaluate to a node-set. The selected set of
nodes is processed in document order, unless a sorting specification is
present"

So, <xsl:apply-templates/>

   is the same as

<xsl:apply-templates
 select="*|comment()|processing-instruction()|text()"/>

So now you can see where the behavior of an XSLT processor to recursively
descend the tree is specified. It is in the built-in rule for elements and
the root node, and the default behavior of <xsl:apply-templates/>. What you
want to do is override these things.

You're going to start at the root node whether you like it or not. So first
override the template for the root node, and jump right to the elements that
have no children:

<xsl:template match="/">
   <xsl:apply-templates select="//*[not(*)]"/>
</xsl:template>

The select pattern means:
	//      descendants
	*       that are elements with any name
	[]      that have these characteristics:
	not()     do not
	*         have child elements

Thus, the template above means "when processing the root node, don't do
anything other than process the nodes in the set specified by this pattern".
By "process" I mean execute the template that best matches each selected
node individually.

Then override the default template for element nodes by going up to the
parent element instead of down to the various child nodes:

<xsl:template match="*">
   <!-- do something with this element -->
   <xsl:text>I am at element '</xsl:text>
   <xsl:value-of select="name(.)"/>
   <xsl:text>'&#xA;</xsl:text>
   <!-- go do something with the parent element -->
   <xsl:apply-templates select=".."/>
</xsl:template>

While this will ascend the source tree from each leaf, you don't know where
you have already been, so you will return to top of the tree one time per
leaf in the original set. Perhaps someone else can offer a solution for
ascension without revisitation.


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


Current Thread