Re: [xsl] Newbie question - does the built-in template rules output the attribute node?

Subject: Re: [xsl] Newbie question - does the built-in template rules output the attribute node?
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
Date: Mon, 17 Oct 2005 16:53:43 -0400
Paul,

You asked this question a few days ago; catching up on the list I came across it, but it seems it hasn't been answered yet.

At 10:43 AM 10/13/2005, you wrote:
Another newbie question, this time about XSL itself
rather than xsltproc. (sorry!)

Please not to apologize!


Quoting from XSLT for Dummies, it says:

------------------------------------8<----------------------------------
For text and attribute nodes, a built-in template rule copies their
text through into the result tree:
<xsl:template match="text()|@*">
<xsl:value-of select="."/>
</xsl:template>
In this rule, the match pattern returns all text nodes with text() and
all attribute nodes with @*.
The xsl:value-of instruction then transforms the current node to the
result tree as text.

------------------------------------8<----------------------------------

However, if I run this against a blank stylesheet:

------------------------------------8<----------------------------------
<!-- miniscore.xml -->
<score id="1">Text here
   <film name="I should see this attribute">A Little Princess</film>
   <composer>Patrick Doyle</composer>
   <year>1995</year>
   <grade>100</grade>
</score>

------------------------------------8<----------------------------------
The result is:

------------------------------------8<----------------------------------
<?xml version="1.0" encoding="utf-8"?>Text here
A Little Princess
Patrick Doyle
1995
100
------------------------------------8<----------------------------------

However, since the attribute node name is supposedly matched,
I expected:

------------------------------------8<----------------------------------
<?xml version="1.0" encoding="utf-8"?>Text here
I should see this attribute
A Little Princess
Patrick Doyle
1995
100
------------------------------------8<----------------------------------

Can anyone tell me where I'm wrong?

What the dummies book left out (or maybe is says it somewhere else) is what the built-in template rule for elements does:


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

... with the effect of telling the processor "keep going: process this element's children".

The critical detail is that *attributes are not counted among an element's children*.

In other words, the built-in traversal, running along the child:: axis by default, never selects attributes, so they are never matched by their own built-in template.

To tweak this, try a stylesheet that has just this one template:

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

you will find your attribute values appearing.

BTW select="child::* | attribute::*" can be shortened as select="*|@*".

We like to say that attributes have been disinherited; they know who their parents are, but their parents, when asked for their children, never mention them. They are definitely second-class citizens in the data model.

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