Closed rvdb closed 6 years ago
the interesting things is that "doc('test.xml')" is a XSLT/Saxon function, not from eXist-db; I am wondering why it works in the first place (if it works at all), I did not expect it to work, I am not sure it is intend to work actually.
i.e. how is exist-db able to serve out the right document? there is no absolute path. what happens if you provide a compile url starting with http://localhost:8080/.....
?
Well, document() is an XSLT function (http://www.w3.org/TR/xslt20/#function-document); doc() is an XPath/XQuery function (http://www.w3.org/TR/xpath-functions/#func-doc). Both are supported by Saxon: http://saxonica.com/documentation/index.html#!functions/fn. The documentation for doc() documents the URI argument as:
The URI of the required document (relative to the static base URI)
By default the URI is dereferenced using the conventional URL behaviour, as implement by the Java runtime library; this behaviour can be modified by means of a user-supplied URIResolver.
(http://saxonica.com/documentation/index.html#!functions/fn/doc)
Actually, loading the document with the relative URI in eXist doesn't seem the problem (see style3.xsl); only when that document is processed directly, without first copying it into a fresh XSLT variable. Note: when the files are run from the file system (not from the db), no errors occur.
Indeed, replacing the relative URI with http://localhost:8080/.....
makes it work everywhere.
As you said, the document()
and doc()
functions are the XSLT functions, that work on a URL.
The question is: what is the URL? is essence..... there is none, maybe a '''xmldb:exist:///''' like string but strictly that is not an URL.
There fore resolving the document is problematic, or even impossible.
the let $style := doc('/db/apps/test_xsltbug/style.xsl')
is completely different story. in this case eXist-db serialises the complete XML structure to a data stream which is consumed by the XSLT processor. The XSLT processor will never see the actual location......
ps. just after my first response I saw you CC-ed the exist-open list on this subject. I think it is a better medium for discussion; I don't think there is a bug here, maybe a imperfection.
what is the status? what if full http:// or xmldm:// addresses are used?
Saxon allows you to plugin a URI resolver, so you can have any URI do whatever you wish when passed to the doc() or collection() functions. It would not be much effort for us to create and add an eXist URI Resolver for Saxon. I think that would be the way to solve this...
A long time ago I filed some code for this, I thought it was actually working; might be wrong :-(
Behaviour is unchanged in RC2.2. W.r.t. paths, it succeeds with absolute paths:
<xsl:copy-of select="doc('http://localhost:8080/exist/apps/test_xsltbug/test.xml')"/>
<xsl:copy-of select="doc('xmldb:///db/apps/test_xsltbug/test.xml')"/>
It fails with a relative path: <xsl:copy-of select="doc('test.xml')"/>
, throwing following error:
An attribute node (xml:id) cannot be created after a child of the containing element
I want to stress that the fault in this case does NOT seem to lie with loading the document, but with applying <xsl:copy-of/> to that document. This is illustrated by the fact that when <xsl:copy-of/> is replaced with an identity copy via <xsl:apply-templates/>, node structures loaded with doc() using a relative path do get copied without errors:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="#all" version="2.0">
<xsl:template match="/">
<xsl:apply-templates select="doc('test.xml')" mode="copy"/>
</xsl:template>
<xsl:template match="@*|node()" mode="copy">
<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="copy"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Seems to have been fixed in eXist-3.6.0...
Testing with eXist-2.1, I've bumped into an XSLT bug. The problem occurs when an XSLT stylesheet that has been stored in eXist-db imports an XML document via the
doc()
function, and tries to process its nodes.This simple stylesheet (
style.xsl
) illustrates the problem:The
$test
variable imports following simple document (test.xml):Yet, when applying this stylesheet onto itself with following xquery:
...instead of just returning an identical copy of the test.xml file, an error is thrown:
This is clearly a bug, and seems to suggest that nodes are processed in wrong order when they have been imported in an XSLT stylesheet with the doc() function.
I have tried to find workarounds for this annoying bug, and discovered that the problem does not happen when:
$test
XML structure is constructed as an XSLT variable and next processed (see style2.xsl)$test
variable is imported with the doc() function, but first copied indirectly via an identity transform with <xsl:apply-templates/> before further processing (style3.xsl
)For convenient testing, I have attached a backup of the test collection containing these documents, including a test xquery (test.xq) which executes all 3 versions of the XSLT stylesheet and reports errors where they occur.
While the problem is related to XSLT processing with Saxon, I think this is an eXist issue: the problem only occurs when the XSLT stylesheet is executed with transform:transform() from within the database. When the collection is stored and run from the file system, all goes well. Also, when run with pure Saxon (without eXist), no errors occur with the transformation.
I hope this provides some clues for debugging...
( Sorry, I don't know any better way to attach the backup of the test collection in this Githb tracker than by renaming it as a .jpg file. In order to use it, store and rename it to test_xsltbug.zip. )