Re: : RE: [xsl] suppressing default template rules

Subject: Re: : RE: [xsl] suppressing default template rules
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Thu, 28 Mar 2002 09:31:27 +0000
Hi Aseef,

> This could very much be elementary (sorry), but i really didnt
> follow in which order the nodes got processed and why i got the
> contents of firstname and lastname elements printed twice before
> adding the template rule for custdet element. Can anyone give some
> tip as to what really happened with the two cases.

Your XML structure was:

<custdet>
  <employee />
  <firstname>first</firstname>
  <lastname>last</lastname>
</custdet>

Which translates to a tree that looks like:

 / (root node)
 +- custdet
    +- employee
    +- firstname
    |   +- 'first'
    +- lastname
        +- 'last'

When the processor starts processing, it starts at the root node and
tries to find a template that matches it. If it doesn't find one, it
uses the built-in template:

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

which applies templates to the root node's child nodes -- in this case
the custdet element. Again, if there's no template for an element (as
there isn't for the custdet element), the processor uses the built-in
template:

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

This applies templates to all the children of the element: the
employee element, the firstname element and the lastname element. So
you get templates applied once to the firstname and lastname elements
because of the built-in template for the custdet element.

When the processor applies templates to the employee element, it finds
the following template:

<xsl:template match="employee">
  <xsl:apply-templates select="//firstname"/>
  <xsl:apply-templates select="//lastname"/>
</xsl:template>

Inside the template, you have two xsl:apply-templates instructions,
which apply templates to all the firstname and lastname elements in
the document. So templates get applied to the firstname and lastname
elements for a second time, from within this template.

If you want to only process the firstname and lastname elements once,
then you can either add a template for the custdet element that only
processes the employee element:

<xsl:template match="custdet">
  <xsl:apply-templates select="employee" />
</xsl:template>

Or you can change the template for the employee element so that it
doesn't apply templates for the firstname or lastname elements (or
remove that template entirely).

But as Jarno said, if the firstname and lastname are information about
the employee, it probably makes more sense to alter your XML
structure, so that the firstname and lastname elements are nested
inside the employee:

<custdet>
  <employee>
    <firstname>first</firstname>
    <lastname>last</lastname>
  </employee>
</custdet>

You should then change your template for the employee element so that
the paths are relative to the employee element you're on rather than
getting all the firstname and lastname elements in the document:

<xsl:template match="employee">
  <xsl:apply-templates select="firstname" />
  <xsl:apply-templates select="lastname" />
</xsl:template>

Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/


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


Current Thread