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

Reply via email to