Re: [xslt] No user context available when apply stylesheet loads an external entity
- From: Rush Manbert <rush manbert com>
- To: The Gnome XSLT library mailing-list <xslt gnome org>
- Subject: Re: [xslt] No user context available when apply stylesheet loads an external entity
- Date: Thu, 17 Nov 2005 16:54:54 -0800
Rush Manbert wrote:
Hi,
I have an application that uses libxml2 to parse an XML file, then uses
libxslt to apply one or more XSL stylesheet transformations to the
document. The result of this is then extracted as a HTML string and
given to a web browser control to display.
I have registered an external entity loader with libxml by calling
xmlSetExternalEntityLoader(). I have a set of search paths that are
registered, and the loader function handles searching them in the proper
order.
The problem that I have is that I need to have multiple windows open,
each of which displays a separate XHTML document. Each window can have
its own set of search paths for file loading. This means that when my
external entity loader is called, I need to have enough context so that
I can find the proper set of search paths.
For parsing the XML file, I discovered and started using
xmlCtxtReadFile(). I allocate a parser context, use the _private data
member to store my context, then retrieve it in the entity loader.
However, when I apply a XSL stylesheet transformation to my document,
using xsltApplyStylesheetUser(), it often loads other XHTML source
files. This calls the loader, but the parser context that is passed in
has no context information that I can use to find the correct path set.
The myDoc member has a value of 0, and there is no pointer to the
xsltTransformContext, so I can't get at its _private data member. I also
tried setting the _private data member in the transform context, hoping
that it might be propagated to the parser context, but that doesn't happen.
Have I missed something here? How am I supposed to know my application
context when I am in the entity loader? I suppose I could guard the XSL
transformation with a semaphore, and set the context info into some
global location that the loader can retrieve from, but that seems like a
nasty hack.
I am using libxml2-2.6.19 and libxslt-1.1.14.
More info:
I found the xsltSetLoaderFunc() function, so I copied the function
xsltDocDefaultLoaderFunc() and made my own version that adds this line
right before calling xmlLoadExternalEntity():
pctxt->_private = ((xsltTransformContextPtr)ctxt)->_private;
(The cast is required because the transform context ptr was cast to
void* in the call.) I verified that the transform context pointer was
the same as that passed to xsltApplyStylesheetUser(), so I thought I was
home free. However, it turns out that xsltLoadDocument() is hard coded
to call xsltDocDefaultLoaderFunc(), and the function to set a new loader
has no effect!
I then searched on the libxslt site and found this:
http://mail.gnome.org/archives/xslt/2004-August/msg00034.html
so this seems to be intentional.
I would like to suggest that the call to xsltDocDefaultLoader() should
pass the xsltTransformContextPtr value, not cast as a void*, and that
xsltDocDefaultLoader() should copy the _private member from the
transform context to the parser context. The parser context is allocated
inside the function, so there can't be anything there to step on. This
way we can set the private data member when we apply a stylesheet and
use it in the entity loader. Otherwise there's just no context
information available that relates back to the program that is using the
library. Does this make sense?
Thanks,
Rush
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]