After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 549552 - document('') not working as expected, when loading xsl from memory
document('') not working as expected, when loading xsl from memory
Status: RESOLVED NOTABUG
Product: libxslt
Classification: Platform
Component: general
1.1.x
Other All
: Normal normal
: ---
Assigned To: Daniel Veillard
libxml QA maintainers
Depends on:
Blocks:
 
 
Reported: 2008-08-27 09:20 UTC by Sebastian Volland
Modified: 2008-08-27 14:32 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description Sebastian Volland 2008-08-27 09:20:27 UTC
Please describe the problem:
(libxslt-1.1.24)

Using the document()-function with an empty document-URI as first parameter (i.e. document('')) works perfectly, if the stylesheet is loaded from a file (e.g. with xsltproc on the command line).

Calling document('') does not return the expected result, if we load the stylesheet from memory (reproducible with the included test program).

The difference is: if we load the stylesheet from memory, the document-URI is empty. But if I understand the spec correctly (http://www.w3.org/TR/xslt#document, 12.1), the empty parameter from the document-function is a special feature, which should work, even if the stylesheet's document-URI is empty:

"[...]; thus document("") refers to the root node of the stylesheet; the tree representation of the stylesheet is exactly the same as if the XML document containing the stylesheet was the initial source document."


Steps to reproduce:

#include <string.h>
#include "libxslt/libxslt.h"
#include "libxslt/xslt.h"
#include "libxslt/xsltInternals.h"

int main(int argc, char ** argv)
{
    xmlDocPtr xsldoc = NULL;
    xmlDocPtr xmldoc = NULL;
    xsltStylesheetPtr sheetp = NULL;
    xsltStylesheetPtr resdoc = NULL;

    int size = 0;
    xmlChar * buf = NULL;

    char * s1;
    char * s2;

    s1 = strdup("<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"> \
\
<xsl:template match=\"/\"> \
    <v><xsl:copy-of select=\"document('')/*[1]/@version\"/></v> \
</xsl:template> \
\
</xsl:stylesheet> \
");

    s2 = strdup("<a/>");

    xsldoc = xmlParseMemory(s1, strlen(BAD_CAST s1));
    sheetp = xsltParseStylesheetDoc(xsldoc);
    xmldoc = xmlParseMemory(s2, strlen(BAD_CAST s2));
    resdoc = xsltApplyStylesheet(sheetp, xmldoc, NULL);
    xmlDocDumpMemory(resdoc, &buf, &size);

    printf(buf);
}



Actual results:
The test program outputs:

<?xml version="1.0"?>
<v/>

Expected results:
processing exactly the same stylesheet on the command line with xsltproc outputs the expected result:

~/tmp/1)> xsltproc a.xsl a.xml 
<?xml version="1.0"?>
<v>1.0</v>


Does this happen every time?
Yes

Other information:
Comment 1 Daniel Veillard 2008-08-27 13:28:03 UTC
In a nutshell impossible to fix by libxslt itself.

Once the XML is parsed from memeory, we don't keep the memory string around.
The XSLT just get the xsldoc pointer to the parsed tree, never the original
XML input.
Since there is no URI to refetch it we just can't magically regenerate the
information.

Don't parse from memory if you don't absolutely have to.
Also note that sometime the parser never get a full string of the XML
when parsing it, for example when building from a push parser context.

  What you are asking for is impossible purely from libxml2/libxslt
with the code as shown.

You can still try to add support by yourself, by keeping the XmL content
around, add a unique URI when parsing the XML from memory (using
xmlReadMemory not the ancient xmlParseMemory) and setting up a private
entity loader (libxml2 doc/examples/io1.c) which then provide the 
requested content when asked for it by libxslt.

I don't think it's a libxml2/libxslt bug as you asked libxslt to generate
informations it never ever got.

Daniel
Comment 2 Sebastian Volland 2008-08-27 14:32:09 UTC
Then I wonder why it works when I set the stylesheet's document-URI to a non-existent file right after parsing the xsl:

xsldoc->URL = strdup("file:///tmp/bogus/mogus");

This is actually our workaround for this problem. The problem with this workaround is, that we get an I/O warning.

Here's the full test program with the workaround:



#include <string.h>
#include "libxslt/libxslt.h"
#include "libxslt/xslt.h"
#include "libxslt/xsltInternals.h"

int main(int argc, char ** argv)
{
    xmlDocPtr xsldoc = NULL;
    xmlDocPtr xmldoc = NULL;
    xsltStylesheetPtr sheetp = NULL;
    xsltStylesheetPtr resdoc = NULL;

    int size = 0;
    xmlChar * buf = NULL;

    char * s1;
    char * s2;
    char * uri;

    s1 = strdup("<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"> \
\
<xsl:template match=\"/\"> \
    <v><xsl:value-of select=\"document('')/*[1]/@version\"/></v> \
</xsl:template> \
\
</xsl:stylesheet> \
");

    s2 = strdup("<a/>");

    xsldoc = xmlParseMemory(s1, strlen(BAD_CAST s1));
    xsldoc->URL = strdup("file:///tmp/bogus/mogus");
    sheetp = xsltParseStylesheetDoc(xsldoc);
    xmldoc = xmlParseMemory(s2, strlen(BAD_CAST s2));
    resdoc = xsltApplyStylesheet(sheetp, xmldoc, NULL);
    xmlDocDumpMemory(resdoc, &buf, &size);

    printf(buf);
}



Output:


~/tmp/libxslt-1.1.24)> ./a.out 
I/O warning : failed to load external entity "file:///tmp/bogus/mogus"
<?xml version="1.0"?>
<v>1.0</v>