[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

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


Subject: Re: [xsl] Re:Excluding a complete branch while identity copying
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
Date: Mon, 13 Oct 2008 12:48:09 -0400

Fraser,

At 01:17 PM 10/11/2008, you wrote:
I think the problem here (for me) was forgetting that (in this
'recursive descent' style) the sytlesheet is defining 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 :-

Cool.


(To Ken's and David's helpful answers, I'm going to add some stuff.)

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.

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 ?

Pretty much.


To take a different tack -- this seems like a detour, but bear with me -- understand that

<xsl:template match="/">
  <xsl:for-each select="/path/to/element">
    <do><stuff/></do>
  </xsl:for-each>
</xsl:template>

is identical, from the point of view of processing (although not from the point of extensibility and flexibility), to:

<xsl:template match="/">
  <xsl:apply-templates select="/path/to/element"/>
</xsl:template>

<xsl:template match="element">
  <do><stuff/></do>
</xsl:template>

and further understand that

<xsl:apply-templates/>

could also be written as

<xsl:apply-templates select="child::node()"/>

Then, as you say, if you don't match a node with a template of your own, it will match the built-in template. For elements, this looks like

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

and for text nodes, this looks like

<xsl:template match="text()">
  <xsl:value-of select="."/>
</xsl:template>

... the distinction here is crucial. The built-in handling for text nodes (which of course you are free to overwrite however you like) doesn't apply templates; instead it writes the text node's value. Applying templates to the children of a text node is as good as suppressing it, since text nodes have no children and applying templates to an empty node set gets you nothing.

Make sense? (Put these bits of information into your brain, mix with the ideas you already have in there, let rise for several hours, and bake.)

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 ?

Yours will copy the input, but it isn't going to work for this application, mostly, since it doesn't actually traverse the tree. It might work with some particular input data, but only if the template you wrote never matches any ancestor of the elements you want to remove. If it does, that ancestor will be copied entirely instead of its children (and their children, etc.) being processed to match templates of their own. Hence, no template will ever match the nodes you want to remove, which is how they are removed.


Ryan's version and mine work pretty much the same way. His doesn't apply templates to all children at once; instead it applies templates to all attributes and to all element children. If you use his, you may note (if you try it) that any comments and processing-instructions will not be copied, since they are not matched by the copying template, and the built-in template that matches them does not copy them. My version of the template matches (and copies, and applies templates to) anything in the input tree including comments and PIs.

Ryan's version is also perhaps a little clearer to programmers who don't know what "node()" means, but who can guess what "*" means.

I hope that helps --
Wendell



======================================================================
Wendell Piez                            mailto:wapiez@xxxxxxxxxxxxxxxx
Mulberry Technologies, Inc.                http://www.mulberrytech.com
17 West Jefferson Street                    Direct Phone: 301/315-9635
Suite 207                                          Phone: 301/315-9631
Rockville, MD  20850                                 Fax: 301/315-8285
----------------------------------------------------------------------
  Mulberry Technologies: A Consultancy Specializing in SGML and XML
======================================================================


Current Thread
Keywords