Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Meaning of "context" in regard to parameters of a calling template

I like to think that I have a good grasp of XSLT, but the following eludes me: Why is an xsl:param not accessible from a called template that does not explicitly declare it? In other words, if I call template B from template A:

Stylesheet 1

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

   <xsl:template match="/" name="A"><!--This template is named "A" for convenience only.-->
      <xsl:param name="hello" select="hello "/>
      <xsl:param name="world" select="world!"/>
      <xsl:call-template name="B"/>
   </xsl:template>

   <xsl:template name="B">
      <xsl:value-of select="concat($hello,$world)"/>
   </xsl:template>

</xsl:stylesheet>

Why does template B not automatically adopt the parameters of template A as part of the context? My rationale is as follows.

Apparently, calling a template does not affect the context in any way:

The selected <xsl:template> is evaluated with no change to the context: it uses the same context item, context position, and context size as the calling template1


Now, what does "context" actually mean in XSLT, or more precisely, is a parameter considered part of the context or not? Among the things that form the context are2:

  • all variable declarations (xsl:variable and xsl:param) that are in scope at the point where an expression is evaluated, as part of the static context
  • the values of all variables that are in scope, as part of the dynamic context

This leads me to believe that the following stylesheet is equal to the first one I have shown:

Stylesheet 2

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

   <xsl:template match="/" name="A">
      <xsl:param name="hello" select="hello "/>
      <xsl:param name="world" select="world!"/>
      <xsl:value-of select="concat($hello,$world)"/>
   </xsl:template>

</xsl:stylesheet>

But obvously, only the second one is correct, whereas the first one produces two errors about missing variable declarations. Why must parameters be explicitly declared in called templates if a template call does not change the context and parameters are considered part of the context?

For clarity:

  • I know how to amend the first stylesheet with xsl:with-param and parameter declarations - that is not what I am asking for.
  • I am aware of tunnel parameters in XSLT 2.0 - you do not have to explain them or suggest them as an alternative. I am not asking for a way to use parameters in a template where they are not declared - I am wondering why they are not available in the first place.

1 My emphasis. See XSLT 2.0 Programmer's Reference, Michael Kay, page 273.
2 See the relevant part of the specification here or refer to Michael Kay's XSLT 2.0 Programmer's Reference, page 84f.

like image 667
Mathias Müller Avatar asked Dec 06 '22 02:12

Mathias Müller


1 Answers

Excellent question, well asked.

The behavior you expect would be natural in a language with dynamic scope. But XSLT uses lexical scope for variables, not dynamic scope.

You ask Now, what does "context" actually mean in XSLT, or more precisely, is a parameter considered part of the context or not?

Short answer: Yes, the parameter is part of the static context, for the expressions in its scope (and its absence is a fact about the static context of expressions elsewhere in the stylesheet); its value is part of the dynamic context for expressions in its scope. And (crucially) the xsl:call-template instruction does affect the context in which expressions are evaluated.

Longer answer: The specifics are to be found in the XSLT 2.0 spec. In section 2.5 the spec tells us that the context is divided into two parts: the static context and the dynamic context. Section 5.4 provides full details; section 5.4.1 lists "in-scope variables" as one component of the static context.

The scope rules for variables are given in section 9.7. The key bit is this:

A local variable binding element is visible for all following siblings and their descendants, with two exceptions: it is not visible in any region where it is shadowed by another variable binding, and it is not visible within the subtree rooted at an xsl:fallback instruction that is a sibling of the variable binding element.

The apparent contradiction you have run into relies crucially on the premise that "calling a template does not affect the context". This premise is not in fact correct, despite the fact that you have it on very good authority.

In section 10.1, the spec says that "the xsl:call-template instruction does not change the focus." It does not say that the instruction leave the context unaffected.

In the passage you quote from Michael Kay's book, I believe the term "context" is perhaps best taken as short for "context item", or perhaps "dynamic context". Even on that reading the sentence is not quite correct: because the dynamic variables component of the context differs, the dynamic context in the called template is not exactly the same as in the calling template. I think you have to cut MK some slack here: the paragraph in question is essentially unchanged from the XSLT 1.0 version of his book, and in XSLT 1.0 there is no explicit representation, in the discussion of context, of the dynamic binding of variables and parameters to names. But I think it's fair to say you've found something in the book MK might wish to change in the next revision.

like image 116
C. M. Sperberg-McQueen Avatar answered Jan 21 '23 03:01

C. M. Sperberg-McQueen