xsl-list
[Top] [All Lists]

Re: [xsl] Re:Excluding a complete branch while identity copying

2008-10-11 14:44:48
At 2008-10-11 18:17 +0100, Fraser Goffin wrote:
I was using something similar but with different results. I had this
template to exclude 'Evens' and this identity (copy) template :-

       <xsl:template match="Evens">

               <xsl:apply-templates/>
       </xsl:template>


       <xsl:template match="*|@*|text()">
               <xsl:copy-of select="."/>
       </xsl:template>

The problem that you have helped me spot is the 'apply-templates'
inside the Evens template, results in all of 'Evens' children being
processed, which then led me down the path of defining similar
templates for each child and ultimately to the text() node for each of
these.

       <xsl:template match="Evens">

               <xsl:apply-templates/>
       </xsl:template>

       <xsl:template match="Evens/Four">

               <xsl:apply-templates/>
       </xsl:template>

       <xsl:template match="Four">

               <xsl:apply-templates/>
       </xsl:template>

       <xsl:template match="Four/text()">

               <xsl:apply-templates/>
       </xsl:template>


Whilst this does produce the correct result it is very messy and unnecessary.

Yep!

I think the problem here (for me) was forgetting that (in this
'recursive descent' style) the sytlesheet is defining the output

I teach it more actively as "constructing the output".

rather than controlling the way that input is processed (i.e. I was
thinking procedurally). So we get to the questions to clarify the
behaviour :-

1.  I had put apply-templates into the 'exclude this node' templates
because I was mistakenly thinking that unless I did that the
processing of the input would stop.

Yes, that is a mistake ... *all* nodes you push at your stylesheet get handled by your template rules or, if not present, then the built-in template rules.

So the clarification is, when you're not taking control of how the
input is processed (by NOT using apply-templates but explicitly
pulling data from the input) then the XSLT processor continues through
the input document in a recursive fashion from top to bottom and nodes
are either processed by specific templates that contain a match
expression that selects that node, or they are processed by the
default template rules.

Is that correct ?

Nope ... not quite. It isn't the XSLT processor that "continues through the input document in a recursive fashion", it is the identity template that you had defined in your stylesheet. If you hadn't had a template match for elements then the built-in template rule for elements would have acted on each element's children.

Everything is in your hands to catch nodes as the come to the stylesheet ... and you even control *which* nodes come to the stylesheet. The *only* assumption made by the processor is at the very start where it pushes the root node at your stylesheet ... no other assumptions are made ... every node is then handled by your template rules or the built-in template rules.

2.  The 'near' identity template that I used does appear to produce
the same results as the one you provided. I suspect that the one
provided by Ryan does also (thanks Ryan) :-

MINE :-

       <xsl:template match="*|@*|text()">
               <xsl:copy-of select="."/>
       </xsl:template>

YOURS :-

       <xsl:template match="node()|@*">
               <xsl:copy>
                       <xsl:apply-templates select="node()|@*"/>
               </xsl:copy>
       </xsl:template>


RYANs :-

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

    <xsl:apply-templates/>
  </xsl:copy>
 </xsl:template>


Can you tell me which one of these is prefable and why ?

Because leaf nodes have no children or attached nodes, the redundant <xsl:apply-templates/> never does anything for those nodes because there are never any nodes addressed to be pushed.

If you wanted to avoid that redundancy, then the identity template could be split into two:

  <xsl:template match="*">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="@*|text()|comment()|processing-instruction()">
    <xsl:copy/>
  </xsl:template>

But then I think you are just cycle counting, and the processor probably already optimized out the addressing of child and attached nodes anyway, so you may as well keep with Wendell's use of the "traditional" identity template:

  <xsl:template match="node()|@*">
     <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
  </xsl:template>

I hope this helps.

. . . . . . . . . . . . Ken


--
Upcoming XSLT/XSL-FO hands-on courses:      Wellington, NZ 2009-01
Training tools: Comprehensive interactive XSLT/XPath 1.0/2.0 video
Video sample lesson:    http://www.youtube.com/watch?v=PrNjJCh7Ppg
Video course overview:  http://www.youtube.com/watch?v=VTiodiij6gE
G. Ken Holman                 mailto:gkholman(_at_)CraneSoftwrights(_dot_)com
Crane Softwrights Ltd.          http://www.CraneSoftwrights.com/s/
Male Cancer Awareness Nov'07  http://www.CraneSoftwrights.com/s/bc
Legal business disclaimers:  http://www.CraneSoftwrights.com/legal


--~------------------------------------------------------------------
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>