-----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]
