[xsl] Duplicate definitions in XSLT 1.0

Subject: [xsl] Duplicate definitions in XSLT 1.0
From: Michael Ludwig <mlu@xxxxxxxxxxxxx>
Date: Wed, 19 Aug 2009 18:46:29 +0200
Running code with different processors I noticed differences in
processing. In particular, I noticed laxness with duplicate definitions
in LibXSLT and Xalan-J. MSXML is non-conformant when duplicates result
from an xsl:include. Saxon 6.5 is conformant in every respect I tested.
Saxon 9, which is bound by XSLT 2.0, is stricter than required by 1.0.

The spec says in section 17:

   A conforming XSLT processor must signal any errors except for those
   that this document specifically allows an XSLT processor not to
   signal. A conforming XSLT processor may but need not recover from any
   errors that it signals.

http://www.w3.org/TR/xslt#conformance

Signaling errors is quite useful, of course; failure to do so has the
potential to hide bugs.

This somewhat lengthy mail presents a number of test cases aiming at
eliciting error messages for duplicate definitions. At the end there
is a small table containing a conformance listing.

I'm posting this here as four (or five) different processors are
involved. (And then point to it on the forums for Xalan and LibXSLT.)

~~~~~~~~

(1) This stylesheet consisting of only one module contains a duplicate
match template:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
    <xsl:template match="/">eins</xsl:template>
    <xsl:template match="/">DUPL</xsl:template>
</xsl:stylesheet>

(2) And so does this stylesheet consisting of two modules:

milu@colinux:~/Werkstatt/xsl/dupldef > expand -t2 includer.xsl
<xsl:stylesheet version="1.0"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
   <xsl:include href="lib.xsl"/>
   <xsl:template match="/">eins</xsl:template>
</xsl:stylesheet>

milu@colinux:~/Werkstatt/xsl/dupldef > expand -t2 lib.xsl
<xsl:stylesheet version="1.0"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
   <xsl:template match="/">DUPL</xsl:template>
</xsl:stylesheet>

The XSLT 1.0 spec says the following in 5.5 (Conflict Resolution for
Template Rules):

   It is an error if [eliminating matching templates based on lower
   import precedence and lower priority] leaves more than one matching
   template rule. An XSLT processor may signal the error; if it does
   not signal the error, it must recover by choosing, from amongst the
   matching template rules that are left, the one that occurs last in
   the stylesheet.

http://www.w3.org/TR/xslt#conflict

(3) Duplicate named templates:

milu@colinux:/tmp/dupldef > expand -t2 dupltmpln.xsl
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
    <xsl:template name="T">eins</xsl:template>
    <xsl:template name="T">DUPL</xsl:template>
    <xsl:template match="/"><xsl:call-template name="T"/></xsl:template>
</xsl:stylesheet>

The XSLT 1.0 spec says in section 6:

   It is an error if a stylesheet contains more than one template with
   the same name and same import precedence.

http://www.w3.org/TR/xslt#named-templates

(4) Duplicate top-level variables:

milu@colinux:/tmp/dupldef > expand -t2 duplvar.xsl
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
    <xsl:variable name="var" select="'eins'"/>
    <xsl:variable name="var" select="'DUPL'"/>
    <xsl:template match="/"><xsl:copy-of select="$var"/></xsl:template>
</xsl:stylesheet>

(5) Duplicate top-level parameters:

milu@colinux:/tmp/dupldef > expand -t2 duplparm.xsl
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
    <xsl:param name="var" select="'eins'"/>
    <xsl:param name="var" select="'DUPL'"/>
    <xsl:template match="/"><xsl:copy-of select="$var"/></xsl:template>
</xsl:stylesheet>

The spec says in section 11.4:

   It is an error if a stylesheet contains more than one binding of a
   top-level variable with the same name and same import precedence.

http://www.w3.org/TR/xslt#variables

The title of said section is "Top-level Variables and Parameters". The
quoted statement could be clearer, but it is intended to refer to both
both xsl:variable and xsl:param.

(6) Duplicate namespace alias declarations:

milu@colinux:~/Werkstatt/xsl/dupldef > expand -t2 duplnsalias.xsl
<xsl:stylesheet version="1.0"
   xmlns:aaa="aaa" xmlns:milu="de.milu.test"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
   <xsl:namespace-alias stylesheet-prefix="aaa" result-prefix="milu"/>
   <xsl:namespace-alias stylesheet-prefix="aaa" result-prefix="xsl"/>
   <xsl:template match="/">
     <aaa:Urmel/>
   </xsl:template>
</xsl:stylesheet>

The spec says in section 7.1.1:

   If a namespace URI is declared to be an alias for multiple different
   namespace URIs, then the declaration with the highest import
   precedence is used. It is an error if there is more than one such
   declaration. An XSLT processor may signal the error; if it does not
   signal the error, it must recover by choosing, from amongst the
   declarations with the highest import precedence, the one that occurs
   last in the stylesheet.

(7) Duplicate attribute set declarations:

milu@colinux:~/Werkstatt/xsl/dupldef > expand -t2 duplattrset.xsl
<xsl:stylesheet version="1.0"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
   <xsl:attribute-set name="a">
     <xsl:attribute name="font-size">2em</xsl:attribute>
   </xsl:attribute-set>
   <xsl:attribute-set name="a">
     <xsl:attribute name="font-size">3em</xsl:attribute>
   </xsl:attribute-set>
   <xsl:template match="/">
     <xsl:element name="Urmel" use-attribute-sets="a"/>
   </xsl:template>
</xsl:stylesheet>

The spec says in section 7.1.4:

   It is an error if there are two attribute sets that have the same
   expanded-name and equal import precedence and that both contain the
   same attribute, unless there is a definition of the attribute set with
   higher import precedence that also contains the attribute. An XSLT
   processor may signal the error; if it does not signal the error, it
   must recover by choosing from amongst the definitions that specify the
   attribute that have the highest import precedence the one that was
   specified last in the stylesheet.

(8) Duplicate output attributes:

<xsl:stylesheet version="1.0"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
   <xsl:output method="text"/>
   <xsl:output method="xml"/>
   <xsl:template match="/"><Elm>Hallo</Elm></xsl:template>
</xsl:stylesheet>

   It is an error if there is more than one such value for an attribute.
   An XSLT processor may signal the error; if it does not signal the
   error, if should recover by using the value that occurs last in the
   stylesheet.

~~~~~~~~

Okay. I tested some processors with regard to duplicate definitions as
per the XSLT 1.0 specification and the above examples.

                            spec  XalJ  LibX  MSXML Sa65  Sa91
(1) match template           RE    R+    R+    R+    W+    W+
(2) same with xsl:include    RE    R+    R+    r-    RE    RE
(3) name template            CE    CE    CE    CE    CE    CE
(4) xsl:variable             CE    --    CE    CE    CE    CE
(5) xsl:param                CE    --    --    CE    CE    CE
(6) xsl:namespace-alias      RE    r-    r-    R+    R+    CE
(7) xsl:attribute-set        RE    R+    r-    R+    R+    R+
(8) xsl:output               RE    R+    R+    R+    R+    CE

Legend:

   CE  : (spec) non-recoverable compilation error
   RE  : (spec) recoverable error
   W+  : (impl) warning, recovery and correct result
   R+  : (impl) recovery and correct result
   r-  : (impl) recovery and wrong result (bug)
   --  : (impl) failure to raise an error (bug)

Versions:

   Xalan-J : 2.7.1
   LibXSLT : 1.1.24
   MSXML6  : 6.0 (I think)
   Saxon65 : 6.5.5
   Saxon9  : 9.1.0.7J (2.0 processor, only for comparison)

Xalan-J is run with the -QC switch, which should give additional
warnings.

It seems both Xalan-J and LibXSLT are non-conformant for three
cases each: both with respect to xsl:param and xsl:namespace-alias;
Xalan-J with respect to xsl:variable; and LibXSLT with respect to
xsl:attribute-set.

MSXML6 is non-conformant with respect to duplicate definitions involving
an xsl:include; not only named templates, as in the example above, but
also duplicate variables, duplicate parameters and maybe other
constructs.

--
Michael Ludwig

Current Thread