XML.com: XML From the Inside Out
oreilly.comSafari Bookshelf.Conferences.

advertisement

Dirty XSLT Output
by John E. Simpson | Pages: 1, 2

So now let's trace the logic of your Transformation #2:

  1. First template rule:
    • Match on any world elements in the source tree.
    • If you get a match, instantiate in the result tree the basic structure of an XHTML document: html, head, and so on, down through a table element.
    • Within the result tree's table element, process all template rules for the country child elements of this world element.
  2. Second template rule:
    • Match on any government element which is a child of a country element. (Note that this does not correspond to the instruction provided by the first template rule's xsl:apply-templates element.)
    • If you get such a match, instantiate in the result tree a tr table-row element, within which will be a single td element and the string-value of the context node's (that is, the country element's) executive_branch/chief_of_state "grandchild."

That looks fine so far. The problem is that your source tree includes a handful of elements (and in one case, a text node) for which there are no explicit template rules. For all these cases -- including the country element which you expressly said (via that xsl:apply-templates) you wanted to be processed -- the built-in template rules are automatically applied. For every one of the elements, therefore -- every one, that is, except world (covered by Transformation #2's first template rule) and the government child(ren) of country elements (from Transformation #2's second template rule) -- every child of that element is processed as if you'd explicitly coded the built-in template rule. This includes the text-node child of the nameelement -- that is, the string "United States of America." This text node gets transferred to the result tree, unchanged, at the point where the name element would normally be processed. So that's why "United States of America" shows up in Transformation #2's result tree where it does.

But what about Transformation #1? Why isn't the name element (with the same text node child) processed there, too?

Let's trace its logic:

  1. First template rule: same as for Transformation #2.
  2. Second template rule:
    • Match on any country element. (Note that this does correspond, exactly, to the instruction provided by the first template rule's xsl:apply-templates element.)
    • If you get such a match, instantiate in the result tree a tr table-row element, within which will be a single td element and the string-value of the context node's (that is, the country element's) government/executive_branch/chief_of_state "great-grandchild."

Why, then, isn't the country element's name descendant processed? Because Transformation #1 overrides, for all country elements, the built-in template rule for elements in general: no children, and hence no descendants, of country will be processed at all by further template rules (built-in or otherwise). If you'd like Transformation #1 to duplicate the results of Transformation #2, just modify its second template rule as follows:

   <xsl:template match="country">
      <xsl:apply-templates
select="appellative"/>
      <tr>
         <td> 
            <xsl:value-of
select="government/executive_branch/chief_of_state"/>
         </td>
      </tr>
   </xsl:template>

Since there's no explicit template rule provided for processing appellative elements, the built-in rules take effect -- trickling all the way down to the text node, "United States of America," which is a child of the name element.

By the way, I often find these built-in template rules (especially the one for text nodes) mildly distracting, especially when debugging a stylesheet. If you're distracted by them, too, feel free to override them with empty explicit template rules of your own. For instance:

   <!-- Suppress all text nodes by default
-->
   <xsl:template match="text()" />

Not everyone agrees with this approach, but it puts more explicit control in the hands of the stylesheet developer. And when I'm developing a stylesheet, that's where I prefer the control to be.

Correction: grouping with XSLT

Also in XML Q&A

From English to Dutch?

Trickledown Namespaces?

From XML to SMIL

From One String to Many

Getting in Touch with XML Contacts

In the July XML Q&A column, I discussed using the generate-id() function, in concert with the key() and current() functions, to group source-tree data. Shortly after that column appeared, I received a nice message from Geert Josten. He used the examples from that column to help test an "XSLT parser" he'd built using the, as he put it, "very unknown programming language called MetaMorphosis (www.ovidius.com)."

Josten said he'd fixed a couple of small problems involving use of the current() and generate-id() functions. But then he went on to point out some flaws in my explanation of how the generate-id() function works.

In particular, the column said, "whatever algorithm it uses [for generating IDs, an XSLT processor must generate the same key value for any given 'seed value' (such as a node's string-value) in a given processing instance." But this statement implies that a node's string-value is alone sufficient for generating a unique ID; in fact, if this were true, two attributes (for example) with the same value would have the same ID. This clearly isn't the case.

Thanks to Geert Josten for pointing out the error.



1 to 1 of 1
  1. More about xslt please
    2002-10-14 20:39:29 sean Ginter
1 to 1 of 1