RE: [xsl] Apply-templates - how to omit top level element tags?

Subject: RE: [xsl] Apply-templates - how to omit top level element tags?
From: "Mike Schinkel" <mikes@xxxxxxxxx>
Date: Fri, 9 Sep 2005 15:34:48 -0400
>> If in what you want for most cases is for elements to be copied by
default.  (If not, yank that identity transform template out of
there.)

I need the identity transform for other aspects of my stylesheet.  I
can't remove it.

>> It's a bit like saying you were using an object from a math library
called calculator and complained
>> calculator.sum(2,3)  didn't give you the right answer.
>> When somewhere above you had done calculator.base(4) and not told us
about it

Because I didn't know I had.  Again, demonstrating the fragility of XSL
because I have to consider everything.  Things like calculator.base(4)
set state, and stateless programming is much more robust than stateful
programming, for the exact reason you mention.

>> I realize you don't like the idea of modes, but just for the
archives, and in case your cases become more complex:

I have no problem with modes, it's just that I don't like writing extra
code that has to be maintained when I don't need to, and in this case I
didn't feel I needed to.


-Mike

-----Original Message-----
From: Jon Gorman [mailto:jonathan.gorman@xxxxxxxxx]
Sent: Thursday, September 08, 2005 8:39 PM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: Re: [xsl] Apply-templates - how to omit top level element tags?

> Not so (I've just learned) when this is also part of the stylesheet:
>
>         <xsl:template match="@*|node()">
>                 <xsl:copy>
>                         <xsl:apply-templates select="@*|node()"/>
>                 </xsl:copy>
>         </xsl:template>
>
> Of course I didn't realize that until I had to produce a cut down
> version of the example to email you before.

And I was just going to comment on this template in your previous email.
You may have figured it out already, but this template is the primary
part of what is called the identity transform.  It'll match whenever
there is not another template that matches a node and copy that element
and then process the children.  It's not as specific as having a
template that has match="Name", but will have the same effect.

In this case, experience in my case shows rather than "skipping" the
node, you might just be better off having a generic

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

If in what you want for most cases is for elements to be copied by
default.  (If not, yank that identity transform template out of
there.)

If you remove that template, I think you'll find most of the other
suggestions on the list also work.

> BTW, I think my comments are stepping on the toes of the "XSLT
> religion", for that I am sorry.  I am just a Secularist and try to
> apply critical thinking whenever possible, but of course I'm human so
> I'm still flawed.

I don't necessarily think that your comments are bother anyone.
Certainly they haven't bothered me.  It's just that a few of them are
misleading, such as "apply-templates" wouldn't work for you.  It's a bit
like saying you were using an object from a math library called
calculator and complained

calculator.sum(2,3)  didn't give you the right answer.

When somewhere above you had done calculator.base(4) and not told us
about it

We of course were scratching our heads and saying that it will work.

Of course, I'm sure you have figured this out already.

Some other methods.

1) modes

I realize you don't like the idea of modes, but just for the archives,
and in case your cases become more complex:



I'm not doing a perfect job.  I'm assuming anything not section is the
header.  You could do a better path that would say "get me all the nodes
before Sections occurs".
<xsl:template match="Guide">
<body>
<xsl:apply-templates mode="head" select="not(Sections)/>
<xsl:apply-templates mode="toc" select="Sections" /> <xsl:apply-template
mode="content" select="Sections"/> <xsl:apply-templates mode="footer" />
</body> </xsl:template> the folllowing are only the "Name" elements, but
for the toc you'd probably produce an ul and then apply-templates to all
of it's children, ect.

<xsl:template match="Name" mode="head">
<!-- if I had a dtd, I would use apply-templates without a mode to
essentially get the low level inline attributes -->
<h1><xsl:apply-templates /></h1> </xsl:template>

<!-- I'm assuming each section has a name and some sort of unique
identifier--> <xsl:template match="Name" mode="toc" > <li><a
href="#{@anchor}"><xsl:apply-templates /></a></li> </xsl:template>

<xsl:template match="Name" mode="content"> <span
style="title"><xsl:apply-templates /></span> </xsl:template>

and generic,
<xsl:template match="Name">
<xsl:apply-templates />
</xsl:template>

2) Just call apply-templates selecting the name and having a template
like <xsl:template match="Name"> <xsl:apply-templates /> </xsl:template>

This means if you change your mind about the default, you only have to
change it in one place.

3) Call template (in this case it would be bad method, but people still
use it) <xsl:call-template name="leaderTitle"/>

<xsl:template name="leaderTitle">
<xsl:for-each select="Name">
<h1><xsl:apply-templates /></h1>
</xsl:for-each>
</xsl:template>

The mode can be useful because you can "share" contexts.  That is, if
there are multiple elements that tend to appear multiple times in the
hierarchy but mean different things in those area they can all share the
same mode.  Think of it as a state machine of sorts.


> >> There are such ways: they're called template rules. Because in XSLT
> transformations the "entirely new context" is usually defined in
> relation to the input document, the primary (though not the only)
> mechanism for relating templates to their context of execution is the
> match pattern.
>
> I'm not familiar with XSLT "template rules"; is this a 2.0 concept?

Nope, ya know those match statements like "@*|node()"?  Those are
template rules, as defined by the XSLT spec, section 5.

Hmmm, from when I started this mail, saved the draft, and had dinner
there's been quite a few postings.  Perhaps I'll go read those
now...probably more than you wanted to know anyhow.  I think you're on
the right track.  I think XSLT handles the XML documents elegantly
enough.  I'm sure you could build it into some other framework if it
made you more comfy (something along the lines of SAX).  XSLT is more
than worth my while to learn, and I certainly would hate to have to
develop another system to handle XML that deals as nicely with it as
XSLT does.  (Well, ok I use SAX on occasion too, but not for the complex
narrative-centric files).

Jon Gorman

Current Thread