Bug 9734 - default initial template
Summary: default initial template
Status: CLOSED FIXED
Alias: None
Product: XPath / XQuery / XSLT
Classification: Unclassified
Component: XSLT 3.0 (show other bugs)
Version: Working drafts
Hardware: PC All
: P2 enhancement
Target Milestone: ---
Assignee: Michael Kay
QA Contact: Mailing list for public feedback on specs from XSL and XML Query WGs
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-05-14 15:18 UTC by Andrew Welch
Modified: 2014-05-15 23:46 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Andrew Welch 2010-05-14 15:18:11 UTC
It would be useful as the stylesheet author to be able to define a default initial template within the stylesheet.

This would allow a transform with no input to be run without the need for the user to supply the name of initial template, apply it to itself.

For example,

<xsl:stylesheet ... 
  default-initial-template="main">

<xsl:template name="main">

This would simplify it for people and applications to run "standalone" transforms.
Comment 1 Michael Kay 2010-07-15 11:26:30 UTC
Reclassified as an enhancement request. The WG is favourably disposed towards it.
Comment 2 Michael Kay 2012-05-17 17:09:37 UTC
I think this is a good idea in principle, but there are details that need to be worked out. It's difficult to define exactly what it means without a concrete API in mind. 

(1) Are we imagining that there are now three principal ways of starting the transformation:

(a) apply-templates to the initial context item

(b) call-template of a specific named template

(c) call-template of the default initial template

and that in the API, the caller would have to be clear which of these three is intended?

(2) Putting something as an attribute on xsl:stylesheet raises questions about multiple stylesheet modules and how different values of this attribute should interact. From this point of view, I think it would be better to have an attribute on xsl:template that labels the template as the initial entry point. It would then be subject to import precedence, with an explicit error if more than one template at the same (highest) precedence is so labelled.

I'm a little inclined to suggest a no-new-syntax solution that says if the stylesheet is invoked as in (c) above, the initial template name is the template called "xsl:main". If it's good enough for C and Java, why can't it be good enough for us?
Comment 3 Michael Kay 2012-06-14 15:41:46 UTC
As indicated at the end of comment #2, my suggestion here is to recognize the tempate name "main" as special. (Not "xsl:main" - I don't think there are any compatibility or other reasons to make that necessary).

Then in ยง2.3, replace "Either a named template, or an initial context item, or both, must be supplied." with "If neither a named template or an initial context item is supplied, the transformation proceeds as if the name "main" were supplied for the initial named template; in this case a named template with the name "main" (in no namespace) must exist.
Comment 4 Florent Georges 2012-06-26 16:57:23 UTC
I like the idea to be able to set the initial template from
within the stylesheet, thanks Andrew!  I have a few comments:

1/ I see the feature a bit differently than in comment #2...
   For me, as soon as the stylesheet defines the default initial
   template, then the stylesheet will start processing at a named
   template (either the default one, or another one specified
   explicitly by the user).  Regardless whether the user
   supplies an input tree or not.

   The best use case I have for this new feature is actually
   requiring an input tree: the stylesheet requires an input
   tree, but provides several entry points (one of them is the
   default, but the user can ask for another entry point).

2/ I really don't like the idea to use just "main" in no
   namespace.  For compatibility reasons of course, but also
   because it does not feel right to use NCName for this purpose.
   "xsl:main" sounds good to me (e.g. there is no need to bind a
   namespace only to use this, as the XSLT namespace is most
   likely already bound to a prefix).

3/ Regarding the previous point, I would prefer anyway to have
   xsl:stylesheet/@initial-template to set the name of the
   default initial template.  If we use the other approach (using
   a specific name, "main" or "xsl:main" or whatever), an
   importing stylesheet won't be able to override the main entry
   point and still call the overridden one.  If it can override
   the default initial template *name* though, it will be able to
   set another entry point and call the overridden one simply
   because they won't have the same name anymore.
Comment 5 Abel Braaksma 2012-06-28 16:19:27 UTC
If we use xsl:main, I'd expect it to be x:main, xslt:main or likewise depending on the chosen namespace prefix for the XSL namespace.

If we use main there's the potential for conflicts, maybe not in the main stylesheet, but in imported/included stylesheets.

If we use #main (my original preference), MK mentioned "we only use tokens like #all where we need to use a value that isn't a name."

I'd prefer #main because it's distinguishable and in line with #all, #default etc. Who knows, maybe in a next version someone comes up with #last for a template that must be called at the end of the transformation. If so, we'll be glad that we chose either a QName or an octothorp-prefixed name.

I understand the reluctance for using the octothorp version, but consider:

<xsl:template mode="#all">...
<xsl:apply-templates mode="#current">...
<xsl:apply-templates name="#main">

It simply is more clear, imho, and fits existing naming.

(breaking off because discussion is now)
Comment 6 dnovatchev 2012-06-29 02:50:29 UTC
I would like to propose a slightly different solution that eliminates completely the problems of naming the initial template (in case it is named), or of conflict resolution.

We modify the syntax of <xsl:template> as follows:

 1. A new attribute of <xsl:template is introduced: "initial-template="{yes/no}". 

 2. The "initial-template" attribute is mutually exclusive with any of the "match" or "name" attributes. It is a static error if an <xsl:template> instruction has the "initial-template" attribute specified and also has a "match" or a "name" (or both) attribute specified.

 3. It is a static error if a stylesheet module contains more than one template having an "initial-template" attribute with value "yes".

 4. If a template with  initial-template="yes" is residing in a stylesheet module that isn't the primary stylesheet module in the transformation, its initial template is ignored.
Comment 7 Michael Kay 2012-06-29 10:35:07 UTC
The approach in comment #6 has some appeal. We would be able to say that if initial-template="yes" is present, there must be no contained parameters. We could even require a child xsl:context-item element with mandatory "required" and "as" attributes to enforce a bit of discipline on stylesheet authors.

I'm not sure we should prevent such a template also having "name" and/or "match" attributes if required. They would be useful because they would allow the stylesheet to be invoked using APIs that do not yet support the initial-template mechanism, for example the Ant invocation API.
Comment 8 dnovatchev 2012-06-29 14:32:39 UTC
In reply to Comment 7.

Yes, we can specify all useful restrictions like not specifying parameters and must-have non-empty body.

As for "the stylesheet to be invoked using APIs that do not yet support the
initial-template mechanism", I don't have experience with any such APIs. 

I believe that one of the use cases for the default initial template feature is exactly to make it simpler for such APIs to invoke a transformation -- for example, not to need specifying any initial template name at all.

If any such API allows configurable command-line invocation, then the configgured command line simply will not specify any name for an initial template.
Comment 9 Michael Kay 2012-07-19 08:21:19 UTC
Here's a concrete proposal.

(1) reorganize bullets 3, 4, and 5 of 2.3 initiating a transformation. The caller may choose one of two ways of initiating the transformation

(a) by evaluating apply-templates implicitly selecting the initial context item, with a selected initial mode, which defaults to the unnamed mode. In this case an initial context item must be supplied.

(b) by evaluating call-template to the initial template, with a selected template name, which defaults to the name of the default initial template, defined below. In this case the initial context item is optional. If no template name is supplied then a default initial template must exist.

The default initial template is the template that has the attribute initial-template="yes", if such a template exists. If more than one template carries this attribute, the one with highest import precedence is chosen. If this leaves more than one, a dynamic error is reported.

(2) add the attribute initial-template=yes|no to xsl:template. It is an error to set this to yes on a template that has any xsl:param children with required="yes". It is an error to set this to yes on a template that has no xsl:context-item child. A template that has the attribute initial-template="yes" may also have name and or match attributes, but neither name or match is required. If a template has the attribute initial-template="yes" then the only permitted value for the visibility attribute is "public".

(I'd like to add a third mode of invocation, by calling a global function, but that's a separate proposal).
Comment 10 Michael Kay 2013-02-11 14:58:12 UTC
This feature is now in the spec.
Comment 11 Abel Braaksma 2014-05-15 23:46:24 UTC
For historical accuracy it's worthwhile to add that the proposal in comment#9 has been replaced at some point by the reserved name "xsl:initial-template" as template name, which serves the same purpose: it is the default starting point of the transformation.

See http://www.w3.org/TR/xslt-30/#invoking-initial-template, first bullet.