Re: [xml] _private member of xmlParserCtxt in xmlExternalEntityLoader callback



Hi,
Here is sample code which simulates our system - all data should be loaded
from database, so we need connection information inside external entity
loader.

//----------------------------------------------------
....

xmlExternalEntityLoader defaultLoader;



// Load data from database

xmlParserInputPtr entLoader(const char *URL, const char* ID,
xmlParserCtxtPtr ctxt)

{

                xmlParserInputPtr out = 0;

std::cout << "URL = " << URL << "  _private ="

 << ctxt->_private << " state = " << ctxt->instate << std::endl;

                // Only can load files if _private contains connection info

                if(ctxt->_private){

                                out = defaultLoader(URL, ID, ctxt);    //
for testing - call standard loader

                }

return out;

}



int main(int argc, char* argv[])

{

                .

                // Initialize libxml

                xmlInitParser();

                xmlSubstituteEntitiesDefault(0);

                xmlLoadExtDtdDefaultValue = 6;

                defaultLoader = xmlGetExternalEntityLoader();

                xmlSetExternalEntityLoader(entLoader);

                ..

                // Preloaded document can look like this..

                xmlChar *txt = (xmlChar*)"<?xml version=\"1.0\"
encoding=\"UTF-8\"?>"

                                                "<!DOCTYPE book SYSTEM
\"dtd/book.dtd\" ["

                                                "<!ENTITY %
PublisherGraphics SYSTEM \"graphics.xml\">"

                                                "%PublisherGraphics;"

                                                "<!ENTITY frontmatter SYSTEM
\"fm.xml\">"

                                                "<!ENTITY chapter1 SYSTEM
\"ch1_.xml\">"


"]><book>&frontmatter;<body>&chapter1;</body></book>";

                xmlParserCtxtPtr ctxt = 0;

ctxt = xmlCreateDocParserCtxt(txt);

                if(ctxt){

                // Database connection info

                                ConnectionInfo connection_info;

                ...

                                ctxt->_private = &connection_info;       //
Setup ctxt

                xmlParseDocument(ctxt);



                ..

                                // Work with parsed doc from ctxt->myDoc

..

                }

xmlCleanupParser();

                return 0;

}

 //----------------------------------------

Here is what I got from entLoader():

URL = graphics.xml  _private =0012FF58 state = 3
URL = dtd/ncbi-book.dtd  _private =0012FF58 state = 3
URL = dtd/e-xsl.dtd  _private =0012FF58 state = 3
URL = dtd/e-xsl/isoamsa.ent  _private =0012FF58 state = 3
URL = dtd/e-xsl/ncbibook.ent  _private =0012FF58 state = 3
URL = dtd/notations.dtd  _private =0012FF58 state = 3
URL = dtd/e-xsl/ncbibook.ent  _private =0012FF58 state = 3
URL = fm.xml  _private =00000000 state = 0
URL = chapters/ch1_.xml  _private =00000000 state = 0

I've debugged the code with Visual C++ debugger and found inside parser.c :

static int
xmlParseExternalEntityPrivate(... , xmlParserCtxtPtr oldctxt, ...)
{
...
ctxt = xmlCreateEntityParserCtxt(URL, ID, NULL);  // <-- inside this
function new ParserCtxt  will be created and _private member will not be
copied from oldctxt
....
}

Call stack:
xmlParseExternalEntityPrivate() < xmlParseReference() < xmlParseContent() <
xmlParseElement() < xmlParseDocument() < main()....

inside xmlCreateEntityParserCtxt () I found call to external entity loader
with newly created xmlParserCtxt
I've created new function

xmlParserCtxtPtr
xmlCreateEntityParserCtxtWithData(const xmlChar *URL, const xmlChar *ID,
const xmlChar *base, void *data);

the only difference from xmlCreateEntityParserCtxt is las parameter which I
assign to _private memeber of new xmlParserCtxt
This solves my problem. May be it will be usefull for our people - if so, I
can send my libxml2 changes
I've also checked all other calls to xmlCreateEntityParserCtxt for entire
library and found only 3 of them. I think it will be safe to change them
to xmlCreateEntityParserCtxtWithData.

Regards,
Alex



----- Original Message -----
From: "Daniel Veillard" <veillard redhat com>
To: "Asorokin" <asorokin ncbi nlm nih gov>
Cc: <xml gnome org>
Sent: Wednesday, September 25, 2002 6:55 PM
Subject: Re: [xml] _private member of xmlParserCtxt in
xmlExternalEntityLoader callback


On Wed, Sep 25, 2002 at 03:21:08PM -0400, Asorokin wrote:
Hi,
I'm trying to use my private data inside  redefined external entity
loader.
Inside my callback I found what if parser state ctxt->instate is equal
to
XML_PARSER_START
then ctxt->_private is NULL . In other parser states the _private member
seems to be Ok.

  When do you set-up ctxt->_private ?

For some reasons I can't use global variable to get my private data
inside
callback. Can anybody
suggest how to get private data inside redefined external entity loader
when ctxt->instate == XML_PARSER_START

  A priori I don't see why you would have this behaviour, but it all
depend when you initialize it and the kind of interface you use, are
you using the push parser interface. Give more informations, this
is not sufficient !

Daniel

--
Daniel Veillard      | Red Hat Network https://rhn.redhat.com/
veillard redhat com  | libxml GNOME XML XSLT toolkit  http://xmlsoft.org/
http://veillard.com/ | Rpmfind RPM search engine http://rpmfind.net/






[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]