- From: Werner Donné <werner.donne@re.be>
- Date: Tue, 13 Nov 2001 11:19:55 -0500 (EST)
- To: xsl-editors@w3.org
I your explanation you say: "Of course, you could do without explicit extensions and instead make the user assign priorities, but this would be less user friendly." This is not the case because only the highest priority will match. Within a template there is no way to direct apply-templates to another template which would also match but which has a lower priority. However, this is needed to implement the equivalent of "next-match", which is an enveloping mechanism. Another thing is that the "extensions" are aware of being an extension. This is not necessary. I think the power of polymorphism in XSLT would lie in the ability to express some transformation logic for an element in terms of a generic selection along some axis, i.e. a selection which is not more specific than "axis::*". Such transformation logic would consist of several templates, of which some could match nodes along the generic axis. The latter would not be executed if a more specific match for the same context exists elsewhere. However, both should be executed. Let's look at an example. Say we have some element "authorgroup", which can contain "author", "editor" and "corpauthor" in any order and quantity. The element declaration would be as follows: <!ELEMENT authorgroup ((author|editor|corpauthor)+)> The first two templates in the following example only want to set the children of authorgroup in a comma-separated sequence, without bothering about how these children will be transformed. The latter will have their own, more specific, template. When these only match in the context of an authorgroup, they will precede the first two templates, which will not be executed. This means the generic sequence logic is broken. <xsl:template match="authorgroup/child::*[1]"> <xsl:apply-templates select="child::*"/> </xsl:template> <xsl:template match="authorgroup/child::*[position()>1]"> <xsl:text>, </xsl:text> <xsl:apply-templates select="child::*"/> </xsl:template> <xsl:template match="authorgroup/author"> <!-- Something for author --> </xsl:template> <xsl:template match="authorgroup/editor"> <!-- Something for editor --> </xsl:template> <xsl:template match="authorgroup/corpauthor"> <!-- Something for corpauthor --> </xsl:template> This could be solved by using priorities. The first two templates would have priority -1. The sequencing logic would then have to be replicated in the three consecutive templates like this: <xsl:template match="authorgroup/child::*[1]" priority="-1"> <xsl:apply-templates select="child::*"/> </xsl:template> <xsl:template match="authorgroup/child::*[position()>1]" priority="-1"> <xsl:text>, </xsl:text> <xsl:apply-templates select="child::*"/> </xsl:template> <xsl:template match="authorgroup/child::*[1][name()='author']"> <!-- Something for author --> </xsl:template> <xsl:template match="authorgroup/child::*[position()>1][name()='author']"> <xsl:text>, </xsl:text> <!-- Something for author --> </xsl:template> <xsl:template match="authorgroup/child::*[1][name()='editor']"> <!-- Something for editor --> </xsl:template> <xsl:template match="authorgroup/child::*[position()>1][name()='editor']"> <xsl:text>, </xsl:text> <!-- Something for editor --> </xsl:template> <xsl:template match="authorgroup/child::*[1][name()='corpauthor']"> <!-- Something for corpauthor --> </xsl:template> <xsl:template match="authorgroup/child::*[position()>1][name()='corpauthor']"> <xsl:text>, </xsl:text> <!-- Something for corpauthor --> </xsl:template> This situation is still under control, but suppose the element declaration of authorgroup was as follows: <!ELEMENT authorgroup ((author|editor|collab|corpauthor|othercredit)+)> The stylesheet could for example not specify anything specific for "collab" and "othercredit" in the context of authorgroup. However, an independent party could want to add such a specification. To do that, he would have to examine our stylesheet to discover any generic logic and then replicate it. This creates a dependency between stylesheets. Another solution is using modes. It would look like this: <xsl:template match="authorgroup/child::*[1]"> <xsl:apply-templates select="." mode="extension"/> </xsl:template> <xsl:template match="authorgroup/child::*[position()>1]"> <xsl:text>, </xsl:text> <xsl:apply-templates select="." mode="extension"/> </xsl:template> <xsl:template match="authorgroup/author" mode="extension"> <!-- Something for author --> </xsl:template> <xsl:template match="authorgroup/editor" mode="extension"> <!-- Something for editor --> </xsl:template> <xsl:template match="authorgroup/corpauthor" mode="extension"> <!-- Something for corpauthor --> </xsl:template> Now the sequence logic does not have to be replicated, but the extension templates are linked to the extended ones, while they could also serve a purpose on their own or be combined in another stylesheet set. I propose a small extension for this which has very little impact on the current process model, which says that only one template may match for some node. The solution would consist of adding the optional "max-priority" attribute to the "apply-templates" element. Its meaning is that templates with a priority above max-priority are not considered for the current node. The example could then be transformed like this: <xsl:template match="authorgroup/child::*[1]" priority="1"> <xsl:apply-templates select="." max-priority="0.5"/> </xsl:template> <xsl:template match="authorgroup/child::*[position()>1]" priority="1"> <xsl:text>, </xsl:text> <xsl:apply-templates select="." max-priority="0.5"/> </xsl:template> <xsl:template match="authorgroup/author"> <!-- Something for author --> </xsl:template> <xsl:template match="authorgroup/editor"> <!-- Something for editor --> </xsl:template> <xsl:template match="authorgroup/corpauthor"> <!-- Something for corpauthor --> </xsl:template> The two apply-templates statements select the current node again but exclude their containing template in order to avoid a loop. In fact they provide the chance to more specific ones, if they are around, to fill in their thing. The solution is not ideal because it still has a co-operative aspect in it, being the priority. The advantage, however, is that it has no fundamental impact on the process model. It is still expressed in terms of concepts that already exist. A simple additional test against the current node and the priority is needed. This particular example can be solved in other ways of course. I have chosen it for the sake of simplicity. Regards, Werner. -- Werner Donné -- Re BVBA Engelbeekstraat 8 Papenhof 15 B-3300 Tienen B-3583 Beringen tel: (+32) 486 425803 e-mail: werner.donne@re.be
Received on Wednesday, 14 November 2001 09:24:28 UTC