Re: [xsl] rephrased: passing parameters to generic templates

Subject: Re: [xsl] rephrased: passing parameters to generic templates
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
Date: Wed, 12 Apr 2006 11:32:33 -0400
Robert,

You say you need to pass a parameter, but you
don't say why, and as others have said, the
problem you present would be more easily solved
more directly. (Maybe you need to use a parameter
for some other reason that we haven't seen yet.)

Either your path is determined relative to the
anchor element that generates the link, or it is
determined absolutely. (Or it should be
determined some other way you haven't elucidated.)

If it is to be determined relative to the anchor, Andrew's solution will
work:

<xsl:template match="a">
  <a href="{ancestor::para/docBase}">.....

An 'a' element is matched, generating an a with an href whose value references the (first) docBase element child of any ancestor para of the a matched. If your element structure is different from what this assumes, or the traversal logic should be different, the XPath can be modified.

Given your data, you'd probably want to say
href="{ancestor::para/docBase}/{@href}" to construct a complete file
reference.

If the path is to be determined absolutely (once
for the document, in one place), you could either
query directly, as in
href="{/content/para/docBase}/{@href}", or
better, bind "/content/para/docBase" to a global
variable and then reference that, as in
href="{$docpath}/{@href}". David suggested this yesterday.

Contributors to this list are pretty good at
reading between the lines and guessing what you
actually need to know. But we still don't know if
this actually gives you what you need, partly
because of the parameter red herring (if it is a red herring).

XPath was designed precisely to allow you to
crawl around the tree reaching for data, without
having to pass that data around through your
templates. It's true that templates are like
functions, but the input available to those
functions (defined by the processing context of
any template) is much wider (and more complex)
than simply the parameters (arguments) you pass
them, since the entire input tree plus anything
you happen to have bound to variables in scope is
always available. So mostly we don't have to use parameters explicitly.

When any template is executed, it knows:

what node in the tree was matched (the context node)
  (and implicitly, everything else in the input tree querying it
  either absolutely or relative to this node)
how many nodes were selected when this one was selected (the context size)
which one of the set this is (the context position)
all the variables and parameters in scope
  (and implicitly, anything that can be derived from them)
all the XPath/XSLT functions and operators (including extensions in scope)

One of the interesting things about XSLT as a
functional language is that all this info means
that we don't generally need to pass parameters
explicitly since "context" (a magic word in XSLT)
tells us everything we need. Parameters get
really useful when things get fancy, but it isn't clear you're at that point.

Cheers,
Wendell

At 02:41 AM 4/12/2006, you wrote:
Hi,

I noticed I didn't phrase my problem carefully enough (and the example
wasn't correct either - thank's David) - probably too late at night:

I want to convert only certain (html) nodes using a generic template,
but have to pass a parameter to these templates. As the nodes may be
nested within othernodes, I am using the generic copy 'function'

<xsl:template match="@*|node()|text()" priority="-1">
   <xsl:param name="path" select="'zz'"/>
   <xsl:copy>
     <xsl:apply-templates select="@*|node()|text()">
       <xsl:with-param name="path" select="$path"/>
     </xsl:apply-templates>
   </xsl:copy>
</xsl:template>

The more specific template is:

<xsl:template match="/content">
   <test>
     <xsl:apply-templates select="para">
       <xsl:with_param name="path" select="docBase"/>
     </xsl:apply-templates>
   </test>
</xsl:template>

and the element I want to change:

<xsl:template match="a/@href">
   <xsl:param name="path" select="'xx'"/>
   <xsl:attribute name="href"><xsl:value-of select="$path"/>
      <xsl:value-of select="."/></xsl:attribute>
</xsl:template>

A sample xml file could be:
<content>
   <para>
     <docBase>full_path_to_some_directory</docBase>
     This is a test <b>text</b> which should be copied 1:1.
     <a href=3D"local_ref">A reference</a>
     <center><a href=3D"local_ref">A nested reference</a></center>
   </para>
   <para>
     <docBase>next_full_path_to_some_directory</docBase>
     This is a test <b>text</b> which should be copied 1:1.
     <a href=3D"local_ref">A reference</a>
     <center><a href=3D"local_ref">A nested reference</a></center>
   </para>
</content>

I want to use the <docBase> in every <para> to modify the href
of each anhor element.
How can I propagate the parameter's value in the more specific
template into the generic template? The only parameter that is
propagated is the one in the generic template, so all references have
a value of zz...

Thanks in advance, Robert

Departement Informatik   FGB   tel   +41 (0)61 267 14 66
Universitdt Basel                          fax. +41 (0)61 267 14 61
Robert Frank
Klingelbergstrasse 50                 Robert.Frank@xxxxxxxxx
CH-4056 Basel
Switzerland
http:// www.informatik.unibas.ch/personen/frank_r.html


======================================================================
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