diff --git a/LibXML.pm b/LibXML.pm
index 864647f..c552c24 100644
--- a/LibXML.pm
+++ b/LibXML.pm
@@ -724,22 +724,12 @@ sub _init_callbacks {
$icb = $self->{XML_LIBXML_CALLBACK_STACK};
}
- my $mcb = $self->match_callback();
- my $ocb = $self->open_callback();
- my $rcb = $self->read_callback();
- my $ccb = $self->close_callback();
-
- if ( defined $mcb and defined $ocb and defined $rcb and defined $ccb ) {
- $icb->register_callbacks( [$mcb, $ocb, $rcb, $ccb] );
- }
- $icb->init_callbacks();
+ $icb->init_callbacks($self);
}
sub _cleanup_callbacks {
my $self = shift;
$self->{XML_LIBXML_CALLBACK_STACK}->cleanup_callbacks();
- my $mcb = $self->match_callback();
- $self->{XML_LIBXML_CALLBACK_STACK}->unregister_callbacks( [$mcb] );
}
sub __read {
@@ -2075,12 +2065,14 @@ sub CLONE_SKIP { 1 }
#-------------------------------------------------------------------------#
package XML::LibXML::InputCallback;
-use vars qw($_CUR_CB @_GLOBAL_CALLBACKS @_CB_STACK);
+use vars qw($_CUR_CB @_GLOBAL_CALLBACKS @_CB_STACK $_CB_NESTED_DEPTH @_CB_NESTED_STACK);
BEGIN {
$_CUR_CB = undef;
@_GLOBAL_CALLBACKS = ();
@_CB_STACK = ();
+ $_CB_NESTED_DEPTH = 0;
+ @_CB_NESTED_STACK = ();
}
sub CLONE_SKIP {
@@ -2202,12 +2194,36 @@ sub unregister_callbacks {
# make libxml2 use the callbacks
sub init_callbacks {
my $self = shift;
+ my $parser = shift;
+
+ #initialize the libxml2 callbacks unless this is a nested callback
+ $self->lib_init_callbacks() unless($_CB_NESTED_DEPTH);
+
+ #store the callbacks for any outer executing parser instance
+ $_CB_NESTED_DEPTH++;
+ push @_CB_NESTED_STACK, [
+ $_CUR_CB,
+ [@_CB_STACK],
+ [@_GLOBAL_CALLBACKS],
+ ];
+ #initialize the callback variables for the current parser
$_CUR_CB = undef;
@_CB_STACK = ();
-
@_GLOBAL_CALLBACKS = @{ $self->{_CALLBACKS} };
+ #attach parser specific callbacks
+ if($parser) {
+ my $mcb = $parser->match_callback();
+ my $ocb = $parser->open_callback();
+ my $rcb = $parser->read_callback();
+ my $ccb = $parser->close_callback();
+ if ( defined $mcb and defined $ocb and defined $rcb and defined $ccb ) {
+ unshift @_GLOBAL_CALLBACKS, [$mcb, $ocb, $rcb, $ccb];
+ }
+ }
+
+ #attach global callbacks
if ( defined $XML::LibXML::match_cb and
defined $XML::LibXML::open_cb and
defined $XML::LibXML::read_cb and
@@ -2217,19 +2233,21 @@ sub init_callbacks {
$XML::LibXML::read_cb,
$XML::LibXML::close_cb];
}
-
- $self->lib_init_callbacks();
}
# reset libxml2's callbacks
sub cleanup_callbacks {
my $self = shift;
-
- $_CUR_CB = undef;
- @_GLOBAL_CALLBACKS = ();
- @_CB_STACK = ();
- $self->lib_cleanup_callbacks();
+ #restore the callbacks for the outer parser instance
+ $_CB_NESTED_DEPTH--;
+ my $saved = pop @_CB_NESTED_STACK;
+ $_CUR_CB = $saved->[0];
+ @_CB_STACK = (@{$saved->[1]});
+ @_GLOBAL_CALLBACKS = (@{$saved->[2]});
+
+ #clean up the libxml2 callbacks unless there are still outer parsing instances
+ $self->lib_cleanup_callbacks() unless($_CB_NESTED_DEPTH);
}
$XML::LibXML::__loaded=1;
diff --git a/docs/libxml.dbk b/docs/libxml.dbk
index ec6df23..f52f06e 100644
--- a/docs/libxml.dbk
+++ b/docs/libxml.dbk
@@ -5547,10 +5547,10 @@ $parser->parse_file( $some_xml_file );</programlisting>
</varlistentry>
<varlistentry>
- <term>init_callbacks()</term>
+ <term>init_callbacks( $parser )</term>
<listitem>
- <para>Initializes the callback system before a parsing process.</para>
+ <para>Initializes the callback system for the provided parser before starting a parsing process.</para>
</listitem>
</varlistentry>
diff --git a/t/28new_callbacks_multiple.t b/t/28new_callbacks_multiple.t
index 02c24fc..dd119c5 100644
--- a/t/28new_callbacks_multiple.t
+++ b/t/28new_callbacks_multiple.t
@@ -1,6 +1,6 @@
# $Id$
use Test;
-BEGIN { plan tests => 50 }
+BEGIN { plan tests => 77 }
END { ok(0) unless $loaded }
use XML::LibXML;
use IO::File;
@@ -15,7 +15,8 @@ ok(1);
<x xmlns:xinclude="
http://www.w3.org/2001/XInclude">
<xml>test
<xinclude:include href="/example/test2.xml"/>
-<xinclude:include href="/libxml/test2.xml"/></xml>
+<xinclude:include href="/libxml/test2.xml"/>
+<xinclude:include href="/xmldom/test2.xml"/></xml>
</x>
EOF
@@ -28,6 +29,9 @@ EOF
$icb->register_callbacks( [ \&match_hash, \&open_hash,
\&read_hash, \&close_hash ] );
+ $icb->register_callbacks( [ \&match_xml, \&open_xml,
+ \&read_xml, \&close_xml ] );
+
my $parser = XML::LibXML->new();
$parser->expand_xinclude(1);
@@ -35,7 +39,7 @@ EOF
my $doc = $parser->parse_string($string);
ok($doc);
- ok($doc->string_value(), "\ntest\n..\nbar..\n");
+ ok($doc->string_value(), "\ntest\n..\nbar..\nbarbar\n");
}
{
@@ -73,6 +77,58 @@ EOF
ok($doc->string_value(), "\ntest\n..\n\n \n \n");
}
+{
+ my $string = <<EOF;
+<x xmlns:xinclude="
http://www.w3.org/2001/XInclude">
+<xml>test
+<xinclude:include href="/example/test2.xml"/>
+<xinclude:include href="/xmldom/test2.xml"/></xml>
+</x>
+EOF
+ my $string2 = <<EOF;
+<x xmlns:xinclude="
http://www.w3.org/2001/XInclude">
+<tmp/><xml>foo..<xinclude:include href="/example/test2.xml"/>bar</xml>
+</x>
+EOF
+
+
+ my $icb = XML::LibXML::InputCallback->new();
+ ok($icb);
+
+ my $open_xml2 = sub {
+ my $uri = shift;
+ my $parser = XML::LibXML->new;
+ $parser->expand_xinclude(1);
+ $parser->input_callbacks($icb);
+
+ my $dom = $parser->parse_string($string2);
+ ok($dom);
+
+ return $dom;
+ };
+
+ $icb->register_callbacks( [ \&match_xml, $open_xml2,
+ \&read_xml, \&close_xml ] );
+
+ $icb->register_callbacks( [ \&match_hash2, \&open_hash,
+ \&read_hash, \&close_hash ] );
+
+ my $parser = XML::LibXML->new();
+ $parser->expand_xinclude(1);
+
+ $parser->match_callback( \&match_file );
+ $parser->open_callback( \&open_file );
+ $parser->read_callback( \&read_file );
+ $parser->close_callback( \&close_file );
+
+ $parser->input_callbacks($icb);
+
+ my $doc = $parser->parse_string($string);
+
+ ok($doc);
+ ok($doc->string_value(), "\ntest\n..\n\nfoo..bar..bar\n\n");
+}
+
# --------------------------------------------------------------------- #
# CALLBACKS
@@ -173,3 +229,40 @@ sub match_hash2 {
return 1;
}
}
+
+# --------------------------------------------------------------------- #
+# callback set 4 (perl xml reader)
+# --------------------------------------------------------------------- #
+sub match_xml {
+ my $uri = shift;
+ if ( $uri =~ /^\/xmldom\// ){
+ ok(1);
+ return 1;
+ }
+}
+
+sub open_xml {
+ my $uri = shift;
+ my $dom = XML::LibXML->new->parse_string(q{<?xml version="1.0"?><foo><tmp/>barbar</foo>});
+ ok($dom);
+
+ return $dom;
+}
+
+sub read_xml {
+ my $dom = shift;
+ my $buflen = shift;
+
+ my $tmp = $dom->documentElement->findnodes('tmp')->shift;
+ my $rv = $tmp ? $dom->toString : "";
+ $tmp->unbindNode if($tmp);
+
+ ok(1);
+ return $rv;
+}
+
+sub close_xml {
+ my $dom = shift;
+ undef $dom;
+ ok(1);
+}