-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
Petr Pajas wrote: | behind the problems and what's wrong with the patch? Also, could | anyone who uses LibXML with AxKit examine this in more detail and try | to find a solution suitable for both camps? I'd be very happy to | commit it to the CVS then. I did some experiments and came up with two options to have a solution for both camps:
(1) Apply noxmlcleanupparser.patch to LibXML.xs
With that patch, I cannot reproduce the behaviour as described in http://aspn.activestate.com/ASPN/Mail/Message/perl-xml/1998065 anymore. The error shows up again with an active "xmlCleanupParser();" line (See (http://axkit.org/cgi-bin/viewcvs.cgi/XML-LibXML/LibXML.xs.diff?r1=1.166&r2=1.167) for the changes causing the callback problems). As I do not know why exactly xmlInitParser(); is needed not to mess up things, it very likely would be safe not to ommit xmlCleanupParser(), even if I cannot reproduce the error in a mod_perl+AxKit+otherXML::LibXML-app environment with ommiting it. Therefore I looked for another option to solve the problem:
(2) Enable input callbacks for XML::LibXSLT
With an active "xmlCleanupParser();" line (as its currently the status in LibXML.xs) all the AxKit callbacks are cleared at the last parsing action in Apache::AxKit::Language::LibXSLT ($style->get_dom()) and no callback is set anymore when XML::LibXSLT->parse_stylesheet() is called. The attached patches for LibXSLT.pm and LibXSLT.xs activate explicit input callback handling for XML::LibXSLT and with it, they enable friendly co-existence of AxKit and other XML::LibXML apps in one Apache installation again.
RFC, Michael
- -- IT Services University of Innsbruck 063A F25E B064 A98F A479 1690 78CD D023 5E2A 6688 http://zis.uibk.ac.at/.m/uibk.ac.at_pgp_pubkey.asc -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.1 (MingW32)
iD8DBQFANJyieM3QI14qZogRAoXDAKDv/lTzGnH5uU9cLWq5S/FmVN5kBQCfcNut sd9TlAyFVgHEaIRUg9ZWK00= =zM5S -----END PGP SIGNATURE-----
Index: LibXML.xs =================================================================== RCS file: /home/cvs/XML-LibXML/LibXML.xs,v retrieving revision 1.169 diff -u -b -r1.169 LibXML.xs --- LibXML.xs 2004/02/18 18:53:07 1.169 +++ LibXML.xs 2004/02/19 09:12:09 @@ -796,7 +796,6 @@ if (LibXML_old_ext_ent_loader != NULL ) { xmlSetExternalEntityLoader( (xmlExternalEntityLoader)LibXML_old_ext_ent_loader ); } - xmlCleanupParser(); } void
Index: LibXSLT.pm =================================================================== RCS file: /home/cvs/XML-LibXSLT/LibXSLT.pm,v retrieving revision 1.46 diff -u -r1.46 LibXSLT.pm --- LibXSLT.pm 2003/02/12 16:48:02 1.46 +++ LibXSLT.pm 2004/02/19 11:07:33 @@ -1,5 +1,4 @@ # $Id: LibXSLT.pm,v 1.46 2003/02/12 16:48:02 matt Exp $ - package XML::LibXSLT; use strict; @@ -35,11 +34,11 @@ my $func = shift; my @params = @_; my @perlParams; - + my $i = 0; while (@params) { my $type = shift(@params); - if ($type eq 'XML::LibXML::Literal' or + if ($type eq 'XML::LibXML::Literal' or $type eq 'XML::LibXML::Number' or $type eq 'XML::LibXML::Boolean') { @@ -53,7 +52,7 @@ unshift(@perlParams, $type->new(@nodes)); } } - + $func = "main::$func" unless ref($func) || $func =~ /(.+)::/; no strict 'refs'; my $res = $func->(@perlParams); @@ -72,7 +71,7 @@ } else { if ($value =~ s/'/', "'", '/g) { - $results[-1] = "concat('$value')"; + $results[-1] = "concat('$value')"; } else { $results[-1] = "'$results[-1]'"; @@ -83,46 +82,75 @@ } sub callbacks { - die "callbacks() never worked and has been removed." + my $self = shift; + if (@_) { + my ($match, $open, $read, $close) = @_; + + $self->{XML_LIBXSLT_MATCH} = $match ; + $self->{XML_LIBXSLT_OPEN} = $open ; + $self->{XML_LIBXSLT_READ} = $read ; + $self->{XML_LIBXSLT_CLOSE} = $close ; + } + else { + return + $self->{XML_LIBXSLT_MATCH}, + $self->{XML_LIBXSLT_OPEN}, + $self->{XML_LIBXSLT_READ}, + $self->{XML_LIBXSLT_CLOSE}; + } } sub match_callback { - die "match_callback never worked and has been removed.\nPlease set \$XML::LibXML::match_cb instead"; + my $self = shift; + $self->{XML_LIBXSLT_MATCH} = shift if scalar @_; + return $self->{XML_LIBXSLT_MATCH}; } sub open_callback { - die "open_callback never worked and has been removed.\nPlease set \$XML::LibXML::open_cb instead"; + my $self = shift; + $self->{XML_LIBXSLT_OPEN} = shift if scalar @_; + return $self->{XML_LIBXSLT_OPEN}; } sub read_callback { - die "read_callback never worked and has been removed.\nPlease set \$XML::LibXML::read_cb instead"; + my $self = shift; + $self->{XML_LIBXSLT_READ} = shift if scalar @_; + return $self->{XML_LIBXSLT_READ}; } sub close_callback { - die "close_callback never worked and has been removed.\nPlease set \$XML::LibXML::close_cb instead"; + my $self = shift; + $self->{XML_LIBXSLT_CLOSE} = shift if scalar @_; + return $self->{XML_LIBXSLT_CLOSE}; } sub parse_stylesheet { my $self = shift; if (!ref($self) || !$self->{XML_LIBXSLT_MATCH}) { + #warn "callbacks: $XML::LibXML::match_cb $XML::LibXML::open_cb $XML::LibXML::read_cb $XML::LibXML::close_cb"; return $self->_parse_stylesheet(@_); } local $XML::LibXML::match_cb = $self->{XML_LIBXSLT_MATCH}; local $XML::LibXML::open_cb = $self->{XML_LIBXSLT_OPEN}; local $XML::LibXML::read_cb = $self->{XML_LIBXSLT_READ}; local $XML::LibXML::close_cb = $self->{XML_LIBXSLT_CLOSE}; + + #warn "localised callbacks: $XML::LibXML::match_cb $XML::LibXML::open_cb $XML::LibXML::read_cb $XML::LibXML::close_cb"; $self->_parse_stylesheet(@_); } sub parse_stylesheet_file { my $self = shift; if (!ref($self) || !$self->{XML_LIBXSLT_MATCH}) { + #warn "callbacks: $XML::LibXML::match_cb $XML::LibXML::open_cb $XML::LibXML::read_cb $XML::LibXML::close_cb"; return $self->_parse_stylesheet_file(@_); } local $XML::LibXML::match_cb = $self->{XML_LIBXSLT_MATCH}; local $XML::LibXML::open_cb = $self->{XML_LIBXSLT_OPEN}; local $XML::LibXML::read_cb = $self->{XML_LIBXSLT_READ}; local $XML::LibXML::close_cb = $self->{XML_LIBXSLT_CLOSE}; + + #warn "localised callbacks: $XML::LibXML::match_cb $XML::LibXML::open_cb $XML::LibXML::read_cb $XML::LibXML::close_cb"; $self->_parse_stylesheet_file(@_); } @@ -143,17 +171,17 @@ use XML::LibXSLT; use XML::LibXML; - + my $parser = XML::LibXML->new(); my $xslt = XML::LibXSLT->new(); - + my $source = $parser->parse_file('foo.xml'); my $style_doc = $parser->parse_file('bar.xsl'); - + my $stylesheet = $xslt->parse_stylesheet($style_doc); - + my $results = $stylesheet->transform($source); - + print $stylesheet->output_string($results); =head1 DESCRIPTION @@ -227,14 +255,19 @@ =head2 parse_stylesheet($doc) C<$doc> here is an XML::LibXML::Document object (see L<XML::LibXML>) -representing an XSLT file. This method will return a +representing an XSLT file. This method will return a XML::LibXSLT::Stylesheet object, or undef on failure. If the XSLT is -invalid, an exception will be thrown, so wrap the call to +invalid, an exception will be thrown, so wrap the call to parse_stylesheet in an eval{} block to trap this. =head2 parse_stylesheet_file($filename) Exactly the same as the above, but parses the given filename directly. + +=head2 Input Callbacks + +To define XML::LibXSLT specific input callbacks, reuse the XML::LibXML +input callback API as described in L<XML::LibXML::Document(3)/"Input Callbacks">. =head1 XML::LibXSLT::Stylesheet
Index: LibXSLT.xs =================================================================== RCS file: /home/cvs/XML-LibXSLT/LibXSLT.xs,v retrieving revision 1.56 diff -u -b -r1.56 LibXSLT.xs --- LibXSLT.xs 2003/08/14 20:03:41 1.56 +++ LibXSLT.xs 2004/02/19 11:07:22 @@ -18,6 +18,7 @@ #include <libxml/HTMLtree.h> #include <libxml/xmlIO.h> #include <libxml/tree.h> +#include <libxml/parser.h> #include <libxml/parserInternals.h> #include <libxml/xpathInternals.h> #include "EXTERN.h" @@ -52,6 +53,238 @@ static SV * LibXSLT_debug_cb = NULL; static HV * LibXSLT_HV_allCallbacks = NULL; +static SV * LibXML_match_cb = NULL; +static SV * LibXML_read_cb = NULL; +static SV * LibXML_open_cb = NULL; +static SV * LibXML_close_cb = NULL; + +int +LibXML_input_match(char const * filename) +{ + int results = 0; + SV * global_cb; + SV * callback = NULL; + + if (LibXML_match_cb && SvTRUE(LibXML_match_cb)) { + callback = LibXML_match_cb; + } + else if ((global_cb = perl_get_sv("XML::LibXML::match_cb", FALSE)) + && SvTRUE(global_cb)) { + callback = global_cb; + } + + if (callback) { + int count; + SV * res; + + dTHX; + dSP; + + ENTER; + SAVETMPS; + + PUSHMARK(SP); + EXTEND(SP, 1); + PUSHs(sv_2mortal(newSVpv((char*)filename, 0))); + PUTBACK; + + count = perl_call_sv(callback, G_SCALAR | G_EVAL); + + SPAGAIN; + + if (count != 1) { + croak("match callback must return a single value"); + } + + if (SvTRUE(ERRSV)) { + croak("input match callback died: %s", SvPV_nolen(ERRSV)); + POPs ; + } + + res = POPs; + + if (SvTRUE(res)) { + results = 1; + } + + PUTBACK; + FREETMPS; + LEAVE; + } + + /* warn("matchcb, filename for: %s\n", filename); */ + return results; +} + +void * +LibXML_input_open(char const * filename) +{ + SV * results; + SV * global_cb; + SV * callback = NULL; + + if (LibXML_open_cb && SvTRUE(LibXML_open_cb)) { + callback = LibXML_open_cb; + } + else if ((global_cb = perl_get_sv("XML::LibXML::open_cb", FALSE)) + && SvTRUE(global_cb)) { + callback = global_cb; + } + + if (callback) { + int count; + + dTHX; + dSP; + + ENTER; + SAVETMPS; + + PUSHMARK(SP); + EXTEND(SP, 1); + PUSHs(sv_2mortal(newSVpv((char*)filename, 0))); + PUTBACK; + + count = perl_call_sv(callback, G_SCALAR | G_EVAL); + + SPAGAIN; + + if (count != 1) { + croak("open callback must return a single value"); + } + + if (SvTRUE(ERRSV)) { + croak("input callback died: %s", SvPV_nolen(ERRSV)); + POPs ; + } + + results = POPs; + + SvREFCNT_inc(results); + + PUTBACK; + FREETMPS; + LEAVE; + } + + /* warn("opencb, filename for: %s\n", filename); */ + return (void *)results; +} + +int +LibXML_input_read(void * context, char * buffer, int len) +{ + STRLEN res_len = 0; + const char * output; + SV * global_cb; + SV * callback = NULL; + SV * ctxt = (SV *)context; + + if (LibXML_read_cb && SvTRUE(LibXML_read_cb)) { + callback = LibXML_read_cb; + } + else if ((global_cb = perl_get_sv("XML::LibXML::read_cb", FALSE)) + && SvTRUE(global_cb)) { + callback = global_cb; + } + + if (callback) { + int count; + + dTHX; + dSP; + + ENTER; + SAVETMPS; + + PUSHMARK(SP); + EXTEND(SP, 2); + PUSHs(ctxt); + PUSHs(sv_2mortal(newSViv(len))); + PUTBACK; + + count = perl_call_sv(callback, G_SCALAR | G_EVAL); + + SPAGAIN; + + if (count != 1) { + croak("read callback must return a single value"); + } + + if (SvTRUE(ERRSV)) { + croak("read callback died: %s", SvPV_nolen(ERRSV)); + POPs ; + } + + output = POPp; + if (output != NULL) { + res_len = strlen(output); + if (res_len) { + strncpy(buffer, output, res_len); + } + else { + buffer[0] = 0; + } + } + + FREETMPS; + LEAVE; + } + + /* warn("readcb, asked for: %d, returning: [%d] %s\n", len, res_len, buffer); */ + return res_len; +} + +void +LibXML_input_close(void * context) +{ + SV * global_cb; + SV * callback = NULL; + SV * ctxt = (SV *)context; + + if (LibXML_close_cb && SvTRUE(LibXML_close_cb)) { + callback = LibXML_close_cb; + } + else if ((global_cb = perl_get_sv("XML::LibXML::close_cb", FALSE)) + && SvTRUE(global_cb)) { + callback = global_cb; + } + + if (callback) { + int count; + + dTHX; + dSP; + + ENTER; + SAVETMPS; + + PUSHMARK(SP); + EXTEND(SP, 1); + PUSHs(ctxt); + PUTBACK; + + count = perl_call_sv(callback, G_SCALAR | G_EVAL); + + SPAGAIN; + + SvREFCNT_dec(ctxt); + + if (!count) { + croak("close callback failed"); + } + + if (SvTRUE(ERRSV)) { + croak("close callback died: %s", SvPV_nolen(ERRSV)); + POPs ; + } + + PUTBACK; + FREETMPS; + LEAVE; + } +} + void LibXSLT_free_all_callbacks(void) { @@ -466,6 +699,13 @@ if (doc == NULL) { XSRETURN_UNDEF; } + + xmlInitParser(); + xmlRegisterInputCallbacks((xmlInputMatchCallback) LibXML_input_match, + (xmlInputOpenCallback) LibXML_input_open, + (xmlInputReadCallback) LibXML_input_read, + (xmlInputCloseCallback) LibXML_input_close); + doc_copy = xmlCopyDoc(doc, 1); doc_copy->URL = xmlStrdup(doc->URL); /* xmlNodeSetBase((xmlNodePtr)doc_copy, doc_copy->URL); */ @@ -477,6 +717,9 @@ xsltSetGenericDebugFunc(NULL, NULL); } RETVAL = xsltParseStylesheetDoc(doc_copy); + + xmlCleanupParser(); + if (RETVAL == NULL) { XSRETURN_UNDEF; } @@ -490,6 +733,12 @@ PREINIT: char * CLASS = "XML::LibXSLT::Stylesheet"; CODE: + xmlInitParser(); + xmlRegisterInputCallbacks((xmlInputMatchCallback) LibXML_input_match, + (xmlInputOpenCallback) LibXML_input_open, + (xmlInputReadCallback) LibXML_input_read, + (xmlInputCloseCallback) LibXML_input_close); + if (LibXSLT_debug_cb && SvTRUE(LibXSLT_debug_cb)) { xsltSetGenericDebugFunc(PerlIO_stderr(), (xmlGenericErrorFunc)LibXSLT_debug_handler); } @@ -497,6 +746,9 @@ xsltSetGenericDebugFunc(NULL, NULL); } RETVAL = xsltParseStylesheetFile(filename); + + xmlCleanupParser(); + if (RETVAL == NULL) { XSRETURN_UNDEF; }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]