Dear Sebastian,
At 05:42 AM 3/15/2006, you wrote:
I hope your class went well. You may remember that you were going to
quote me as saying "we're just not used to having things done for us
are we?"
Yes, I do, and I did quote you too, and they were appreciative. :-)
Regarding the problem in hand, I just don't get it. Why should this
work fine:
<xsl:call-template name="does-image-flickr" />
.
.
<xsl:template name="does-image-flickr">
<xsl:choose><!-- photo is a flickr link -->
<xsl:when test="/page/images/image[(_at_)name=$name]/flickr">
^^^^
[variable 'name' is OK]
...and this cause an error:
<xsl:call-template name="does-image-flickr" />
<xsl:call-template name="write-caption">
<xsl:with-param name="cpos"><xsl:value-of select="$cpos"
/></xsl:with-param>
<xsl:with-param name="caption"><xsl:value-of select="$caption"
/></xsl:with-param>
</xsl:call-template>
.
.
<xsl:template name="does-image-flickr">
<xsl:choose><!-- photo is a flickr link -->
<xsl:when test="/page/images/image[(_at_)name=$name]/flickr">
^^^^
[variable 'name' causes an error]
...where the only difference is the call to the 'write-caption'
template that comes _after_ the call to the 'does-image-flickr'
template.
Actually it's not the order that matters at all. Another aspect of
the "side-effect-freeness" (freedom from side effects?) of the
processing model is that the order of templates matters not a whit.
(Actually there are edge cases where it does, but this isn't one of them.)
What matters here is that although you're passing in a value for
$cpos with the call, there is no declaration of a 'cpos' parameter in
the named template being called.
So write it as
<xsl:template name="does-image-flickr">
<xsl:param name="cpos" select="''"/>
<!-- this declaration provides the parameter with an empty string
as its default value -->
<xsl:choose><!-- photo is a flickr link -->
<xsl:when test="/page/images/image[(_at_)name=$name]/flickr">
... and you'll be fine. (Or maybe you want to set the default to
"false()" or something to avoid getting a selection of a node with @name="").
One adjustment to your idea of how this all works is to keep in mind
that when a processor compiles a stylesheet, information about the
order of the templates may not be retained. Each template is like a
function in itself, which has certain information available to it,
which includes the execution context (which node has been matched and
so on), but not anything about any local variables in scope in other
templates. (This way templates can be executed in parallel, or in an
optimized order, without stepping on each other, if the processor so
chooses.) Global variables (declared at the top level of the
stylesheet) are in scope for all templates, but to pass information
between templates, parameters have to be passed, and to provide for
that, they have to be declared in any template that has to be aware of them.
The fact that the call to 'does-image-flickr' works in the first
instance proves to me what I have been lead to believe, namely that
call-template differs from apply-templates in that the local scope is
unchanged as well as the current node list. My experience whilst
writing this template has also served to confirm this.
The execution context is unchanged as far as which node is taken as
the current node, the set of nodes in the current node list, etc.,
but this doesn't include variables declared in a calling template.
I have several
exapmples where templates called using call-template make use of
params defined in the callee without explicitly passing the params
using with-params.
As long as the parameter is declared in the called template, you're
fine; leaving them out of the call just allows them to take the
default value, which can be very useful.
But the reverse -- passing a parameter into a template where it isn't
defined -- isn't possible. The called template doesn't see such a
parameter as being of any interest to it since it hasn't been
declared, and when a reference is made to it, it just takes it to be
some variable not in scope (which it is).
Like an XML document, a stylesheet in XSLT is not a "script" but
rather a tree-shaped thing. Those branches called "templates" present
(tree-shaped) chunks of results that will be "grafted" to the output.
But internally, the templates have no order: they're just laid out
onto the table, as it were, and applied based only on when they match
(or are called by name). When that happens, each one is considered to
be a self-contained, and special accommodation has to be made for it
to "know" anything outside the context of its application. In XSLT
1.0, local variables and parameters fall outside this line. (This has
been modified in 2.0 with "tunnel parameters", which are somewhat
more flexible, although they too have to be declared in templates
where they are actually used, unless I'm mistaken.)
Cheers,
Wendell
======================================================================
Wendell Piez
mailto:wapiez(_at_)mulberrytech(_dot_)com
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
======================================================================
--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--