Re: [xsl] Matching or selecting template problem
Subject: Re: [xsl] Matching or selecting template problem|
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
Date: Thu, 15 Jan 2009 11:25:37 -0500
At 10:34 AM 1/15/2009, you wrote:
There are some advanced aspects of XSLT that I just don't seem to "get."
They'll click. Persistence is key.
(And don't worry about what I think. I assume all my former students
are brilliant -- they were smart enough to come listen to me! :-P But
learning anything takes practice, and Aha moments come at different
times for different people.)
As for the essence of the problem here, you've already put your
finger on it. Selecting and matching do not have to be symmetrical.
Indeed, they're frequently not.
It's perfectly fine and useful to do:
... do something ...
Notice that the selection grabs the title from among the children of
the sec (one level down), but the match on the title looks up the
tree two levels before it succeeds in matching.
An experienced XSLTer will look at this code and be able to say that
assuming there are no other templates getting in the way, the second
template will fire when the title is selected in the first template
*if and only if the sec matched by the first template is also
directly inside a sec*. This is because we can see that the title
selected in the first template has to match "sec/title", so the only
question is what's the sec inside of?
By the same token, if the first template had matched "sec/sec", that
particular question would be answered, and we could be certain that
the second template does match the title selected in the first one.
Generalizing them: you can select elements from wherever you like in
the tree using whatever paths you like, and then match them using
expressions that happen to match them.
As for the problems you're having matching, what you're running into
is a set of restrictions on the grammar for XPath Patterns, which is
not the same as path expressions (although it's defined to look like
a subset). The simple version is that patterns allow only looking
"down" the tree, using the child:: axis or the "//" operator. So
"sec//title" is a legal pattern, and can be used for matching, but
"sec/title/following-sibling::*" is not.
This doesn't prevent you from *selecting* the following siblings of
the title from inside a template matching "title", using the path
expression "following-sibling::*" to select them, and then *matching*
them using whatever patterns you want, such as "sec/*", or "ul" in
mode "title-siblings", or whatever.
Behind all this is a critical point I think David made: this isn't
sequential text processing, and there are no tags involved. This is
tree processing. Your data, for example, looks like this to me:
etc. This means I don't see the 'p' element starting after the
'section' element ends (no start- or end-tags here). I see it inside
the conbody element, appearing after the sections. And ordinarily I
don't think of processing it after the section or the section title;
I think of processing it inside the conbody, same as I do the sections.
Cutting out the extraneous stuff, what this means is that you want to
And you can do this entirely in the template for conbody:
<xsl:apply-templates select="[... loose stuff ...]"/>
Now a bit of confusion, since the question arises how to fill in "loose stuff".
I think it was Ken who offered a simple way to do that before:
... which is good, unless you think that the fancy XPath
"*[not(self::section)]" will confuse the maintenance programmer.
Another way to do it:
This is also elegant, and it works -- with arguably the opposite
problem, since it's very subtle, since what it does is (1) create a
section for every section, and then (2) make a section, and inside it
(3) process everything, but this time throw the sections away.
A third way to do it would use a special mode on one side or the
other, instead of the for-each instruction.
Note that in any case you may also want conditional testing to make
sure you actually have loose stuff, so as not to create an extra
section when you don't want one.
You may also run into trouble if your loose stuff is scattered
throughout your conbody, not just after the last section, and you
want to group it into sections. Note my use of the term "group",
since that is, in effect, a grouping problem.
I hope this helps.
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