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

Subject: Re: [xsl] Apply-templates - how to omit top level element tags?
From: Jon Gorman <jonathan.gorman@xxxxxxxxx>
Date: Thu, 8 Sep 2005 15:19:53 -0500
> But I always wanted "My Title<TradeMark/>" to be converted to "My
> Title(tm)" and I never wanted output to look like this "<Name>My
> Title(tm)</Name>"   All the suggestions here on the list were to create
> extra templates, which greatly increased complexity, but the simple
> answer I learned through experimentation was to tack "node()" onto
> "Name" ala "Name/node()" in the apply-templates select.  In hindsight
> I'm surpised no one suggested that simple solution.

Because it's not really a solution one would ever arrive on based on
what you gave us.   What you are essentially doing is "skipping" the
Name element all together.  The default rules should provide the same
behavior by simply going <apply-templates select="Name" />.  If it
doesn't, you have a conflicting templates.  My gut feeling is either
you have another template that is matching the Name, or you have
altered how the default rules are being applied.  Also, there's
something happening in the templates you're not showing us.  None that
I remembered seeing would ever give <Name>My Title(tm)</Name>.


> >> Pulling relies heavily on value-of and for-each loops, building a
> document by grabbing nodes from the source xml document.  It doesn't use
> apply-templates.  It is tended to be used with more data-centric outputs
> where the input is pretty predictable. ... Push tends to rely on the
> processing model, using apply-templates.  It is used primarily when
> working with "narrative" documents due to their unpredictable nature.
>
> Okay, then that's actually what I've evolved to, mostly, and it helps me
> understand how to think about architecting my docs.

Also, I have a feeling while you are using apply-templates, you're
using them much more in a pull manner.  That is, something that goes
like:

<xsl:template match="foo">
<h1><xsl:apply-templates select="Name/node()"/></h1>
</xsl:template>
</xsl:template match="bar">
<h2><xsl:apply-templates select="Name/node()" /></h2>
</xsl:template>

<xsl:template match="Name">
<xsl:copy-of select="." />
</xsl:template>

<xsl:template match="trademark">(tm)</xsl:template>

So this will work since using "Name/node()" will avoid that Name
template, and still the default rules will be applied to the
trademark, replacing the text.  The instant you start experimenting
though, that Name might match, causing it to print out a copy-of.

Your technique works, and I could imagine doing something similar.
But to me at least in this case it also feels quite unnecessary and
possibly a nightmare to maintain.  Decide if you want a truly
"generic" case and use that as the template.  This should only require
one template to be generic.  Or just rely on the default rules, which
were pretty much designed for this type of work.


> For me, I think one of the problems is the terminology used by the XSLT
> community. They refer to "node" which to me is an abstract concept, but
> rarely "element tags" and "element contents" which is more concrete.
> I'm learning, but find it frustratingly difficult.

If it helps any, XSL processing occurs (unless you manipulate it) as a
tree.  You have different types of nodes, most significantly element
nodes, attribute nodes, and text nodes.  If you want to think of it in
oop lingo, when you are calling value-of you are really calling a
method called "string()" of each of the nodes selected by the select
statement.  Element nodes just call string on all their text and
element nodes.  Text nodes return their value.  This isn't necessarily
100% accurate, but it should give you a better idea of what is
happening.

> Again, we are using the term "side-effects" in different ways.  Let me
> use a different term: "fragility."  I find a large XSL file to be very
> fragile, and it is relatively impossible to encapsulate logic.  If you
> have a large push model XSL file, you have to understand how it works
> throughout, you cannot divide and conquer like I'm used to structured
> and object-oriented programming where, if I code well, I can write a
> subroutine that I can guarantee will work correct, or fail with
> appropriate diagnostics, no matter what is going on in the calling code.

But inheritance in some sense is what we are dealing with here.  It
may matter what state an object is when a method is called, or how the
newly created object has relates to its parent classes.  In a similar
manner, modes can be used as state processing.

> I don't see how to do that in push model XSL.  For that reason, I find
> it very fragile, and frightening, actually.

It can be confusing.  And it seems some of the more advanced
techniques for controlling it without getting horribly confused are
complex.  It's a pity.


>  If there were ways to
> create encapsulation in XSLT, such as the ability to have stylesheets
> call portions of themselves recursively with entirely new contexts, then
> I think it might be possible for them to be much less fragile.

This is what modes and call-templates are typically used for.

>
> >> You seem to be heading in the right direction, but it feels like
> you're playing around with too large of a stylesheet that you don't
> understand.
>
> You are correct, even though I wrote the entire thing (fyi it is
> currently 1440 lines long.) But my comments on inability to encapsulate
> are why (I think) I am having trouble as it seems to understand the
> stylesheet as I have to understand it in its entirety all at the same
> time!

Well, perhaps another piece of advice is to look at the possible
"world" of documents.  Are there sections that like head and body will
always appear?  Perhaps set them in different stylesheets.  Use modes
to keep each one seperate from the start of the processing of the
parent element, and import these into one larger stylesheet.

This might produce more templates then necessary, but sometimes more
can be actually less confusing because it allows you to deal more
cleanly with "what can possibly happen at this point".  When I started
working with XSLT I had similar issues (and also used "doe").  It
became nightmarish until I realized I was struggling against how the
processor was treating the tree and just started controlling the
"flow" of the execution.  Narrative transformations can be among the
most complex, but it is possible.


> Thanks again.  I'll slog through it...

Glad you found one solution that works.  I just tend to like to talk
;).  I'd still recommend once the stylesheet is somewhat stable
"cleaning" through it.

Jon Gorman

Current Thread