xsl:variable, content-constructor, baseURI

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi!

During developing a stylesheet which heavily relies on file inclusion 
(document()-function) I came across some problems in the XSL specification.

Assume not all files are at the same location but spread over different 
directories. During transformation the stylesheet loads these documents and 
applies its templates to the content (and during this process again files may 
have to be imported and evaluated).

The problem addressed here is how to find those files. The names of the files 
to be loaded are inside the XML documents (relative names!!!). May problem 
arises when recursively importing documents from different directories.

Three examples will follow which actually should result in the same behaviour 
but do not. Let's use three simple files:

a.xml:
<import file="lib/b.xml"/>

lib/b.xml:
<import file="c.xml"/>

lib/c.xml:
Text: nothingblalblabla


Stylesheet A processing file a.xml:
<xsl:template match="import">
     <xsl:variable name="x" select="document(@file, .)"/>
     <xsl:apply-templates select="$x">
       ...parameters...
     </xsl:apply-templates>
</xsl:template>

This example works as expected: During transformation of document "a.xml" file 
"lib/b.xml" has to be imported and from there "c.xml". "b.xml" only knows the 
relative position of "c.xml" relative to its own position. Thus the base URI 
of the lib/b.xml/import-node has to be used. Using stylesheet A this works 
fine.

(Yes I could move the document() call to the apply-templates node. However in 
my stylesheet case I have to do it that way as the actual loading and 
composition process is a little bit more complicated. The files presented 
here are just simplified examples showing the problem)


The following is a slightly changed version of A. Now variable "x" will be 
constructed by content constructors and not via the select attribute. Now the 
transformation fails because the transformer forgets the base URI of the 
imported document. Thus while transforming "lib/b.xml" the file "c.xml" will 
be searched relative to the stylesheet URI (which may be somewhere but not 
"lib/") and not relative to "lib/b.xml". This is due to XSLT 2.0: 9.1 
Variables and 9.4 Temporary Trees. Stylesheet B processing file "a.xml":
<xsl:template match="import">
     <xsl:variable name="x" />
             <xsl:copy-of select="document(@file , .)"/>
     </xsl:variable>
     <xsl:apply-templates select="$x">
             ..parameters...
     </xsl:apply-templates>
<xsl:template>


Now one may argue that <xsl:copy-of/> only copies elements and it is not 
supposed to copy the base URI. But as stated above I try do do all IO in a 
callable template. This leads to a the third possible stylesheet. Stylesheet 
C processing file "a.xml":
<xsl:template match="import">
     <xsl:variable name="x" />
             <xsl:call-template name="load-file">
                     <xsl:with-param name="filename" select="@file"/>
             <xsl:call-template name="load-file">
     </xsl:variable>
     <xsl:apply-templates select="$x">
             ...parameters...
     </xsl:apply-templates>
</xsl:template>

In this example no node will be copied (in template "import") while calling 
the template but still the transformer will forget the base URI which gets 
returned correctly by the called tempalte "load-file". Ok "load-file" again 
works via <xsl:copy-of/> - to my knowledge there is no other way!


To my mind there seem to be two problems:

1) XSLT 2.0 Spec, 9.1 Variables: Constructing a variable as it has been done 
in the second and third stylesheet results in an temporary tree which (XSLT 
2.0 Spec, 9.4 Temporary Trees) does not copy the base URI of the original 
elements but changes it to the base URI of the variable binding element 
(which if understand it correctly is the base URI of the stylesheet).

2) I cannot check with Saxon because there is no way to generate the base-uri 
from the result of <xsl:copy-of/> without binding the result to a variable 
(which ignores the base URI). So I just assume that <xsl:copy-of/> forgets 
the base URI, too.

Thus the current WD of XSLT 2.0 does not support an implicit way of 
propagating the base URI via variables or using <xsl:call-template/>. Doing 
more complicated things in XSL in conjunction with the document()-function 
leads to forgetting the base URI. Thinking of named templates as procedure 
like mechanisms returning data (maybe read from a file) this data will NEVER 
be correct according to the original one (i. e. missing base URI). The data 
has to be processed in the called template as far as the base URI-stuff is 
concerned.

Please rethink the design of the XSLT 2.0 Specification in the eras touched by 
<xsl:variables/>/Temporary trees and named templates. To my mind 
<xsl:copy-of/> should copy the base use and temporary trees should not be 
assigned a common, data unrelated base URI. In case the data bound to a 
variable has it's own base URI this should be adopted.

ciao
Volker

- --
Dipl.-Inform. Volker Renneberg
University of the Federal Armed Forces, Munich
85577 Neubiberg, Werner-Heisenberg-Weg 36
Tel.: +49-89-60042253 - Fax.: +49-89-60044447
http://hypsipyle.informatik.unibw-muenchen.de
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.7 (GNU/Linux)

iD8DBQE+gHNGyX+5eQvzMeoRAhIRAKCwdfU+Mc2zKRomQYNd+Jrpx4A80wCgmAc3
qnWrXSXCCaNl4SXGws9Ziko=
=hO13
-----END PGP SIGNATURE-----

Received on Tuesday, 25 March 2003 10:23:16 UTC