Commits

Anonymous committed 2807086

Modified Files:
Changes
+ version notes

LibXML.xs
[fix] multiple parse initialization

perl-libxml-sax.c
- memory leaking
in my test environments now it leaks only with non default
namespaces. this can be related to old versions of the other SAX
packages i use (?)

dom.c
+ corrected ns fixing on imports, so all tests will pass

lib/XML/LibXML/SAX.pm
+ will not recreate a parser instance, if there already is one.

lib/XML/LibXML/SAX/Builder.pm
+ namespace handling: will not set namespaces twice on a note

t/10ns.t
+ namespace tests

Comments (0)

Files changed (7)

 
 1.54
    - Catalog interface is aware about libxml2 configuration
-   - XML::LibXML should work now on system without having zlib installed
+   - XML::LibXML should work now on system without having zlib installed (?)
    - fixed memory management problem introduced in 1.53
    - fixed default iterator of XML::LibXML::Iterator
    - interface for raw libxml2 DOM building functions 
-     (currently just addChild())
+     (currently just addChild(), others will follow)
+   - fixed memory leak in XML::LibXML::SAX (almost not leaking)
+   - fixed namespace handling if nodes are imported to a new DOM.
    - more documentation 
 
 1.53
         else {
             LibXML_old_ext_ent_loader =  NULL; 
         }
-
     }
 
     /*
      * If the parser callbacks are not set, we have to check CLASS wide
      * callbacks.
      */
+
     if ( LibXML_match_cb == NULL ) {
         item2 = perl_get_sv("XML::LibXML::MatchCB", 0);
         if ( item != NULL  && SvTRUE(item2)) 
     
     read_length = LibXML_read_perl(ioref, buffer, 4);
     if (read_length > 0) {
-        ctxt = xmlCreatePushParserCtxt(PSaxGetHandler(),
+        xmlSAXHandlerPtr sax = PSaxGetHandler();
+        ctxt = xmlCreatePushParserCtxt(sax,
                                        NULL,
                                        buffer,
                                        read_length,
 
         xmlFree(ctxt->sax);
         ctxt->sax = NULL;
+
+        xmlFree(sax);
         PmmSAXCloseContext(ctxt);
         xmlFreeParserCtxt(ctxt);
 
         char * ptr;
         int well_formed;
         int ret;
+        xmlSAXHandlerPtr sax = NULL;
     INIT:
         ptr = SvPV(string, len);
         if (len == 0) {
         if (ctxt == NULL) {
             croak("Couldn't create memory parser context: %s", strerror(errno));
         }
-
+       
         PmmSAXInitContext( ctxt, self );
 
+        xmlFree(ctxt->sax);
         ctxt->sax = PSaxGetHandler();
 
-        /* LibXML_init_parser(self); */
         RETVAL = xmlParseDocument(ctxt);
 
         xmlFree( ctxt->sax );
         PmmSAXCloseContext(ctxt);
         xmlFreeParserCtxt(ctxt);
 
+        sv_2mortal(LibXML_error);
         LibXML_cleanup_callbacks();
         LibXML_cleanup_parser(); 
-
     OUTPUT:
         RETVAL
 
 DESTROY( self ) 
         SV * self
     CODE:
-        warn( "DROP PARSER CONTEXT!" );
+        xs_warn( "DROP PARSER CONTEXT!" );
         PmmContextREFCNT_dec( SvPROXYNODE( self ) );
 
 
         }
     }
 
+
     /* tell all children about the new boss */ 
     if ( node && doc && node->doc != doc ) {
         xmlSetTreeDoc(return_node, doc);
     }
- 
-    xmlReconciliateNs( return_node->doc, return_node );
-    
+
+    if ( doc != NULL && return_node != NULL ) {
+        xmlReconciliateNs(doc, return_node);     
+    }
+
     return return_node;
 }
 
     }
     
     domAddNodeToList(newChild, refChild->prev, refChild);
-     xmlReconciliateNs(self->doc, newChild);     
+    xmlReconciliateNs(self->doc, newChild);     
 
     return newChild;
 }

lib/XML/LibXML/SAX.pm

 
 sub _parse_string {
     my ( $self, $string ) = @_;
-    $self->{ParserOptions}{LibParser}      = XML::LibXML->new;
+#    $self->{ParserOptions}{LibParser}      = XML::LibXML->new;
+    $self->{ParserOptions}{LibParser}      = XML::LibXML->new()     unless defined $self->{ParserOptions}{LibParser};
     $self->{ParserOptions}{ParseFunc}      = \&XML::LibXML::parse_string;
     $self->{ParserOptions}{ParseFuncParam} = $string;
     return $self->_parse;

lib/XML/LibXML/SAX/Builder.pm

     }
 
     # build namespaces
+    my $skip_ns= 0;
     foreach my $p ( $self->{NamespaceStack}->get_declared_prefixes() ) {
+         $skip_ns= 1;
         my $uri = $self->{NamespaceStack}->get_uri($p);
         my $nodeflag = 0;
         if ( defined $uri
              and defined $el->{NamespaceURI}
              and $uri eq $el->{NamespaceURI} ) {
-            $nodeflag = 1;
+#            $nodeflag = 1;
+            next;
         }
-        $node->setNamespace($uri, $p, $nodeflag );
+        $node->setNamespace($uri, $p, 0 );
     }
 
     # append
 
 
             if ( defined $attr->{Prefix}
-                 and $attr->{Prefix} eq "xmlns" ) {
+                 and $attr->{Prefix} eq "xmlns" and $skip_ns == 0 ) {
                 # ok, the generator does not set namespaces correctly!
                 my $uri = $attr->{Value};
                 $node->setNamespace($uri,

perl-libxml-sax.c

     xmlNodePtr ns_stack;
     xmlSAXLocator * locator;
     xmlDocPtr ns_stack_root;
-    SV ** handler;
+    SV * handler;
 } PmmSAXVector;
 
 typedef PmmSAXVector* PmmSAXVectorPtr;
 #ifdef HAVE_UTF8
         SvUTF8_on( retval );
 #endif
+
     }
     return retval;
 }
     vec->parser  = parser;
     th = hv_fetch( (HV*)SvRV(parser), "HANDLER", 7, 0 );
     if ( th != NULL && SvTRUE(*th) ) {
-        vec->handler = th  ;
+        vec->handler = newSVsv(*th)  ;
     }
     else {
         vec->handler = NULL  ;
 {
     PmmSAXVector * vec = (PmmSAXVectorPtr) ctxt->_private;
     dTHX;
-
-    vec->handler = NULL;
+    
+    if ( vec->handler ) {
+        SvREFCNT_dec( vec->handler );
+        vec->handler = NULL;
+    }
     SvREFCNT_dec( vec->parser );
 
     xmlFreeDoc( vec->ns_stack_root );
 
 void
 PSaxStartPrefix( PmmSAXVectorPtr sax, const xmlChar * prefix,
-                 const xmlChar * uri, SV ** handler )
+                 const xmlChar * uri, SV * handler )
 {
     dTHX;
-    HV * param = newHV();
+    HV * param;
+    SV * rv;
 
     dSP;
 
+    ENTER;
+    SAVETMPS;
+
+    param = newHV();
     hv_store(param, "NamespaceURI", 12,
              _C2Sv(uri, NULL), NsURIHash);
 
                  _C2Sv(prefix, NULL), PrefixHash);
     }
     else {
+/*         warn("null prefix!\n" ); */
         hv_store(param, "Prefix", 6,
                  _C2Sv("", NULL), PrefixHash);
     }
 
-    
-    ENTER;
-    SAVETMPS;
+    PUSHMARK(SP) ;
+    XPUSHs(handler);
 
-    PUSHMARK(SP) ;
-    XPUSHs(*handler);
-    XPUSHs(newRV_noinc((SV*)param));
+
+    rv = newRV_noinc((SV*)param);
+
+    XPUSHs(rv);
     PUTBACK;
 
     perl_call_method( "start_prefix_mapping", 0 );
-
+    sv_2mortal(rv);
     FREETMPS ;
     LEAVE ;
 }
 
 void
 PSaxEndPrefix( PmmSAXVectorPtr sax, const xmlChar * prefix,
-               const xmlChar * uri, SV ** handler )
+               const xmlChar * uri, SV * handler )
 {
     dTHX;
-    HV * param = newHV();
+    HV * param;
+    SV * rv;
 
     dSP;
 
+    ENTER;
+    SAVETMPS;
+    param = newHV();
     hv_store(param, "NamespaceURI", 12,
              _C2Sv(uri, NULL), NsURIHash);
 
                  _C2Sv(prefix, NULL), PrefixHash);
     }
     else {
+/*         warn("null prefix!\n" ); */
         hv_store(param, "Prefix", 6,
                  _C2Sv("", NULL), PrefixHash);
     }
-    
-    ENTER;
-    SAVETMPS;
 
     PUSHMARK(SP) ;
-    XPUSHs(*handler);
-    XPUSHs(newRV_noinc( (SV*)param ));
+    XPUSHs(handler);
+
+
+    rv = newRV_noinc((SV*)param);
+
+    XPUSHs(rv);
     PUTBACK;
 
     perl_call_method( "end_prefix_mapping", 0 );
 
+    sv_2mortal(rv);
+
     FREETMPS ;
     LEAVE ;
 }
 }
 
 void
-PmmNarrowNsStack( PmmSAXVectorPtr sax, SV **handler )
+PmmNarrowNsStack( PmmSAXVectorPtr sax, SV *handler )
 {
     xmlNodePtr parent = sax->ns_stack->parent;
     xmlNsPtr list = sax->ns_stack->nsDef;
     while ( list ) {
+        xmlNsPtr tmp = list;
         if ( !xmlStrEqual(list->prefix, "xml") ) {
             PSaxEndPrefix( sax, list->prefix, list->href, handler );
         }
-        list = list->next;
+        list = list->next;        
     }
     xmlUnlinkNode(sax->ns_stack);
+    xmlFreeNode(sax->ns_stack);
     sax->ns_stack = parent;
 }
 
 void
 PmmAddNamespace( PmmSAXVectorPtr sax, const xmlChar * name,
-                 const xmlChar * href, SV **handler)
+                 const xmlChar * href, SV *handler)
 {
     xmlNsPtr ns         = NULL;
     xmlChar * nodename  = NULL;
         return;
     }
 
-    nodename = xmlStrdup(sax->ns_stack->name);
-    localname = xmlSplitQName( NULL, nodename, &prefix );
-    xmlFree( nodename );
+    localname = xmlSplitQName( NULL, sax->ns_stack->name, &prefix );
+
+    ns = xmlNewNs( sax->ns_stack, href, name );         
+    PSaxStartPrefix( sax, name, href, handler );
 
     if ( name != NULL ) {
-        ns = xmlNewNs( sax->ns_stack, href, name );         
-        PSaxStartPrefix( sax, name, href, handler );
-        
         if ( sax->ns_stack->ns == NULL
              && xmlStrEqual( prefix , name ) ) {
             sax->ns_stack->ns = ns;
             sax->ns_stack->name = (const xmlChar*) xmlStrdup( localname );
         }
     }
-    else {
-        ns = xmlNewNs( sax->ns_stack, href, NULL );
-        PSaxStartPrefix( sax, NULL, href, handler );
-        if ( prefix = NULL ) {
-            sax->ns_stack->ns = ns;
-        }
+    else if ( prefix == NULL && sax->ns_stack->ns == NULL) {
+        sax->ns_stack->ns = ns;
     }
-
-    if ( prefix != NULL ) {
-        xmlFree( prefix );
-    }
-    if ( localname != NULL ) {
-        xmlFree( localname );
-    }
+    xmlFree( prefix );
+    xmlFree( localname );
 }
 
 HV *
 PmmGenElementSV( pTHX_ PmmSAXVectorPtr sax, const xmlChar * name )
 {
     HV * retval = newHV();
+    SV * tmp;
 
     xmlNsPtr ns = NULL;
     if ( name != NULL && xmlStrlen( name )  ) {
         hv_store(retval, "Name", 4,
                  _C2Sv(name, NULL), NameHash);
 
-        if ( sax->ns_stack->ns != NULL ) { 
-            localname = xmlSplitQName(NULL, name, &prefix);
- 
-            ns = PmmGetNsMapping( sax->ns_stack, prefix );
-            if ( ns != NULL ) {
-                if ( sax->ns_stack->ns == NULL ) {
-                    sax->ns_stack->ns = ns;
-                    xmlFree( (xmlChar*)sax->ns_stack->name );
-                    sax->ns_stack->name = (const xmlChar*)xmlStrdup(localname);
-                }
-            }
-            xmlFree(prefix);
-            xmlFree(localname);
+        if ( sax->ns_stack->ns != NULL ) {  
+            ns = sax->ns_stack->ns;
+/*             warn("found ns") ; */
+        }
 
-        }
-        else {
-            ns = sax->ns_stack->ns ;
-        }
+        tmp = _C2Sv("",NULL);
         
         if ( ns != NULL ) {
+/*             warn(" namespaced element\n" ); */
+
             hv_store(retval, "NamespaceURI", 12,
                      _C2Sv(ns->href, NULL), NsURIHash);
             if ( ns->prefix ) {
             }
             else {
                 hv_store(retval, "Prefix", 6,
-                         _C2Sv("", NULL), PrefixHash);                
+                         tmp, PrefixHash);
             }
 
             hv_store(retval, "LocalName", 9,
                      _C2Sv(sax->ns_stack->name, NULL), LocalNameHash);
-        } 
+        }
         else {
             hv_store(retval, "NamespaceURI", 12,
-                     _C2Sv("", NULL), NsURIHash);
+                     tmp, NsURIHash);
             hv_store(retval, "Prefix", 6,
-                     _C2Sv("", NULL), PrefixHash);
+                     SvREFCNT_inc(tmp), PrefixHash);
             hv_store(retval, "LocalName", 9,
                      _C2Sv(name, NULL), LocalNameHash);
+        }
+    }
 
-        }
-    }            
     return retval;
 }
 
     int namelen = 0;
     int urilen = 0;
     xmlChar * retval = NULL;
+
+    if ( name == NULL ) {
+        return NULL;
+    }
     namelen = xmlStrlen( name );
     if ( nsURI != NULL ) {
         urilen = xmlStrlen( nsURI );
     }
 
-
     retval =xmlStrncat( retval, "{",1 );
     if ( nsURI != NULL ) {
         retval =xmlStrncat( retval, nsURI, urilen );
 
 HV *
 PmmGenAttributeHashSV( pTHX_ PmmSAXVectorPtr sax,
-                       const xmlChar **attr, SV ** handler )
+                       const xmlChar **attr, SV * handler )
 {
     HV * retval     = NULL;
     HV * atV        = NULL;
     xmlChar * localname   = NULL;
     xmlChar * prefix      = NULL;
 
+    retval = newHV();
+
     if ( ta != NULL ) {
-        retval = newHV();
+
         while ( *ta != NULL ) {
             atV = newHV();
             name = *ta;  ta++;
             value = *ta; ta++;
 
             if ( name != NULL && xmlStrlen( name ) ) {
-                localname = xmlSplitQName(NULL, name, &prefix);
 
                 hv_store(atV, "Name", 4,
                          _C2Sv(name, NULL), NameHash);
-                hv_store(atV, "Value", 5,
-                         _C2Sv(value, NULL), ValueHash);
+                if ( value != NULL ) {
+                    hv_store(atV, "Value", 5,
+                             _C2Sv(value, NULL), ValueHash);
+                }
 
-                if ( prefix != NULL ) {
-                    if ( xmlStrEqual( "xmlns", prefix ) ) {
-                        PmmAddNamespace( sax,
-                                         localname,
-                                         value,
-                                         handler);
-
-                        nsURI = "http://www.w3.org/2000/xmlns/";
-
-                        hv_store(atV, "Prefix", 6,
-                                 _C2Sv(prefix, NULL), PrefixHash);
-                        hv_store(atV, "LocalName", 9,
-                                 _C2Sv(localname,NULL), LocalNameHash);
-                        hv_store(atV, "NamespaceURI", 12,
-                                 _C2Sv("http://www.w3.org/2000/xmlns/",NULL),
-                                 NsURIHash);
-                    }
-                    else {
-                        ns = PmmGetNsMapping( sax->ns_stack, prefix );
-
-                        if ( ns != NULL ) {
-                            nsURI = ns->href;
-
-                            hv_store(atV, "NamespaceURI", 12,
-                                     _C2Sv(ns->href, NULL), NsURIHash);
-                            hv_store(atV, "Prefix", 6,
-                                     _C2Sv(prefix, NULL), PrefixHash);
-                            hv_store(atV, "LocalName", 9,
-                                     _C2Sv(localname, NULL), LocalNameHash);
-                        }
-                        else {
-                            hv_store(atV, "NamespaceURI", 12,
-                                     _C2Sv("",NULL), NsURIHash);
-                            hv_store(atV, "Prefix", 6,
-                                     _C2Sv("", NULL), PrefixHash);
-                            hv_store(atV, "LocalName", 9,
-                                     _C2Sv(name, NULL), LocalNameHash);
-                        }
-                    }
-                    xmlFree( prefix );
-                }
-                else if ( xmlStrEqual( "xmlns", name ) ) {
+                if ( xmlStrEqual( "xmlns", name ) ) {
                     /* a default namespace */
                     PmmAddNamespace( sax, NULL, value, handler);  
                     nsURI = "http://www.w3.org/2000/xmlns/";
 
                     hv_store(atV, "Prefix", 6,
-                             _C2Sv(localname, NULL), PrefixHash);
+                             _C2Sv(name, NULL), PrefixHash);
                     hv_store(atV, "LocalName", 9,
                              _C2Sv("",NULL), LocalNameHash);
                     hv_store(atV, "NamespaceURI", 12,
                              NsURIHash);
                     
                 }
-                else {
+                else if (xmlStrncmp("xmlns:", name, 6 ) == 0 ) {
+                    localname = xmlSplitQName(NULL, name, &prefix);                        
+                    PmmAddNamespace( sax,
+                                     localname,
+                                     value,
+                                     handler);
+                  
+                    nsURI = "http://www.w3.org/2000/xmlns/";
+                    
                     hv_store(atV, "Prefix", 6,
-                             _C2Sv("",NULL), PrefixHash);
+                             _C2Sv(prefix, NULL), PrefixHash);
+                    hv_store(atV, "LocalName", 9,
+                             _C2Sv(localname,NULL), LocalNameHash);
+                    hv_store(atV, "NamespaceURI", 12,
+                             _C2Sv(nsURI,NULL),
+                             NsURIHash);
+                    xmlFree( prefix );
+                }
+                else if ( ns = PmmGetNsMapping( sax->ns_stack, prefix ) ) {
+                    localname = xmlSplitQName(NULL, name, &prefix);        
+                        
+                    hv_store(atV, "NamespaceURI", 12,
+                             _C2Sv(ns->href, NULL), NsURIHash);
+                    hv_store(atV, "Prefix", 6,
+                             _C2Sv(ns->prefix, NULL), PrefixHash);
                     hv_store(atV, "LocalName", 9,
                              _C2Sv(localname, NULL), LocalNameHash);
+                    xmlFree( prefix );
+                }
+                else {
                     hv_store(atV, "NamespaceURI", 12,
                              _C2Sv("",NULL), NsURIHash);
-                    
+                    hv_store(atV, "Prefix", 6,
+                             _C2Sv("", NULL), PrefixHash);
+                    hv_store(atV, "LocalName", 9,
+                             _C2Sv(name, NULL), LocalNameHash);
                 }
-                
-                keyname = PmmGenNsName( localname, nsURI );
+
+                keyname = PmmGenNsName( localname!= NULL ? localname: name,
+                                        nsURI );
 
                 len = xmlStrlen( keyname );
                 PERL_HASH( atnameHash, keyname, len );
             }            
         }
     }
+
     return retval;
 }
 
     dTHX;
     HV* real_obj          = (HV *)SvRV(sax->parser);
     HV* empty             = newHV();
-    SV ** handler         = sax->handler;
+    SV * handler         = sax->handler;
+
+    SV * rv;
 
     if ( handler != NULL ) {
         dSP;
         SAVETMPS;
         
         PUSHMARK(SP) ;
-        XPUSHs(*handler);
-        XPUSHs(newRV_noinc((SV*)empty));
+        XPUSHs(handler);
+        XPUSHs(sv_2mortal(newRV_inc((SV*)empty)));
         PUTBACK;
         
         count = perl_call_method( "start_document", 0 );
         PUSHMARK(SP) ;
 
     
-        XPUSHs(*handler);
+        XPUSHs(handler);
 
 
         if ( ctxt->version != NULL ) {
             hv_store(empty, "Encoding", 8,
                      _C2Sv(ctxt->encoding, NULL), EncodingHash);
         }
-        XPUSHs(newRV_noinc((SV*)empty ));
+        rv = newRV_noinc((SV*)empty);
+        XPUSHs( rv);
 
         PUTBACK;
         
         count = perl_call_method( "xml_decl", 0 );
-        
+        sv_2mortal(rv);
+
         FREETMPS ;
         LEAVE ;
     }
     PmmSAXVectorPtr  sax  = (PmmSAXVectorPtr)ctxt->_private;
     int count             = 0;
     dTHX;
-    SV * attrhash         = NULL;
+    HV * attrhash         = NULL;
     HV * real_obj         = (HV *)SvRV(sax->parser);
     HV * element          = NULL;
-    SV ** handler         = sax->handler;
-    
+    SV * handler         = sax->handler;
+    SV * rv;
+    SV * arv;
+
     dSP;
     
     ENTER;
 
     PmmExtendNsStack(sax, name);
 
-    attrhash = (SV*) PmmGenAttributeHashSV(aTHX_ sax, attr, handler );
+    attrhash = PmmGenAttributeHashSV(aTHX_ sax, attr, handler );
     element  = PmmGenElementSV(aTHX_ sax, name);
 
-    if ( attrhash != NULL ) {
-        hv_store( element,
-                  "Attributes",
-                  10,
-                  newRV_noinc(attrhash),
-                  AttributesHash );
-    }
-    else {
-        hv_store( element,
-                  "Attributes",
-                  10,
-                  newRV_noinc((SV*)newHV()),
-                  AttributesHash );
-    }
+    arv = newRV_noinc((SV*)attrhash);
+    hv_store( element,
+              "Attributes",
+              10,
+              arv,
+              AttributesHash );
     
     PUSHMARK(SP) ;
-    XPUSHs(*handler);
-    XPUSHs(newRV_noinc((SV*)element));
+
+    XPUSHs(handler);
+    rv = newRV_noinc((SV*)element);
+    XPUSHs(rv);
     PUTBACK;
 
     count = perl_call_method( "start_element", 0 );
-
-    SPAGAIN ;
+    
+    sv_2mortal(rv) ;
 
     FREETMPS ;
     LEAVE ;
 
+
     return 1;
 }
 
 PSaxEndElement(void *ctx, const xmlChar * name) {
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr)ctx;
     PmmSAXVectorPtr  sax  = (PmmSAXVectorPtr)ctxt->_private;
-    int count             = 0;
     dTHX;
-    HV* real_obj          = (HV *)SvRV(sax->parser);
-    SV ** handler         = sax->handler;
+    int count;
+/*     HV* real_obj          = (HV *)SvRV(sax->parser); */
+    SV * handler         = sax->handler;
+    SV * rv;
+    HV * element;
 
     dSP;
 
     SAVETMPS;
 
     PUSHMARK(SP) ;
-    XPUSHs(*handler);
-    XPUSHs(newRV_noinc((SV*)PmmGenElementSV(aTHX_ sax, name)));
+    XPUSHs(handler);
+
+    element = PmmGenElementSV(aTHX_ sax, name);
+    rv = newRV_noinc((SV*)element);
+
+    XPUSHs(rv);
     PUTBACK;
 
     count = perl_call_method( "end_element", 0 );
 
+    sv_2mortal(rv);
+
     FREETMPS ;
     LEAVE ;
 
     int count = 0;
     dTHX;
     HV* real_obj = (HV *)SvRV(sax->parser);
-    HV* empty = newHV();
-    SV ** handler = sax->handler;
+    HV* element;
+    SV * handler = sax->handler;
+    
+    SV * rv = NULL;
 
     if ( ch != NULL && handler != NULL ) {
         xmlChar * data = xmlStrndup( ch, len );
         SAVETMPS;
 
         PUSHMARK(SP) ;
-        XPUSHs(*handler);
-        XPUSHs(newRV_noinc((SV*)PmmGenCharDataSV(aTHX_ sax,data)));
+        XPUSHs(handler);
+        element = PmmGenCharDataSV(aTHX_ sax,data);
+        rv = newRV_noinc((SV*)element);
+        XPUSHs(rv);
         PUTBACK;
 
         count = perl_call_method( "characters", 0 );
 
+        sv_2mortal(rv);
+
         FREETMPS ;
         LEAVE ;
 
     int count = 0;
     dTHX;
     HV* real_obj = (HV *)SvRV(sax->parser);
-    HV* empty = newHV();
-    SV ** handler = sax->handler;
+    HV* element;
+    SV * handler = sax->handler;
+    
+    SV * rv = NULL;
 
     if ( ch != NULL && handler != NULL ) {
         xmlChar * data = xmlStrdup( ch );
         SAVETMPS;
 
         PUSHMARK(SP) ;
-        XPUSHs(*handler);
-        XPUSHs(newRV_noinc((SV*)PmmGenCharDataSV(aTHX_ sax,data)));
+        XPUSHs(handler);
+        element = PmmGenCharDataSV(aTHX_ sax,data);
+        rv = newRV_noinc((SV*)element);
+        XPUSHs(rv);
         PUTBACK;
 
         count = perl_call_method( "comment", 0 );
 
+        sv_2mortal(rv);
+
         FREETMPS ;
         LEAVE ;
 
     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr)ctx;
     PmmSAXVectorPtr sax = (PmmSAXVectorPtr)ctxt->_private;
     int count = 0;
-
     dTHX;
     HV* real_obj = (HV *)SvRV(sax->parser);
-    HV* empty = newHV();
-    SV ** handler = sax->handler;
+    HV* element;
+    SV * handler = sax->handler;
+    
+    SV * rv = NULL;
 
     if ( ch != NULL && handler != NULL ) {
         xmlChar * data = xmlStrndup( ch, len );
         SAVETMPS;
 
         PUSHMARK(SP) ;
-        XPUSHs(sax->parser);
-        XPUSHs(newRV_noinc((SV*)PmmGenCharDataSV(aTHX_ sax,data)));
+        XPUSHs(handler);
+        element = PmmGenCharDataSV(aTHX_ sax,data);
+        rv = newRV_noinc((SV*)element);
+        XPUSHs(rv);
         PUTBACK;
 
         count = perl_call_pv( "XML::LibXML::_SAXParser::cdata_block", 0 );
 
+        sv_2mortal(rv);
+
         FREETMPS ;
         LEAVE ;
 
     }
 
     return 1;
+
 }
 
 int
     dTHX;
     HV* real_obj          = (HV *)SvRV(sax->parser);
     HV* empty             = newHV();
-    SV ** handler         = sax->handler;
+    SV * handler         = sax->handler;
+
+    SV * element;
+    SV * rv = NULL;
 
     if ( handler != NULL ) {
         dSP;
         SAVETMPS;
 
         PUSHMARK(SP) ;
-        XPUSHs(*handler);
-        XPUSHs(newRV_noinc((SV*)PmmGenPISV(aTHX_ sax, target, data)));
+        XPUSHs(handler);
+        element = PmmGenPISV(aTHX_ sax, target, data);
+        rv = newRV_noinc((SV*)element);
+        XPUSHs(rv);
 
         PUTBACK;
 
         count = perl_call_method( "processing_instruction", 0 );
 
+        sv_2mortal(rv);
+
         FREETMPS ;
         LEAVE ;
     }
     memset(retval, 0, sizeof(xmlSAXHandler));
 
     retval->startDocument = (startDocumentSAXFunc)&PSaxStartDocument;
+
+    /* libxml2 will not handle perls returnvalue correctly, so we have 
+     * to end the document ourselfes
+     */
     retval->endDocument   = NULL; /* (endDocumentSAXFunc)&PSaxEndDocument; */
 
     retval->startElement  = (startElementSAXFunc)&PSaxStartElement;
 use Test;
-BEGIN { plan tests=>16; }
+BEGIN { plan tests=>21; }
 use XML::LibXML;
 use XML::LibXML::Common qw(:libxml);
 
     ok( $e2->setNamespace("http://kungfoo", "bar") );
     ok( $a->setNamespace("http://kungfoo", "bar") );
     ok( $a->nodeName, "bar:kung" );
+}
+
+print "# 5. importing namespaces\n";
+
+{
+
+    my $doca = XML::LibXML->createDocument;
+    my $docb = XML::LibXML->new()->parse_string( <<EOX );
+<x:a xmlns:x="http://foo.bar"><x:b/></x:a>
+EOX
+
+    my $b = $docb->documentElement->firstChild;
+
+    my $c = $doca->importNode( $b );
+
+    my @attra = $c->attributes;
+    ok( scalar(@attra), 1 );
+    ok( $attra[0]->nodeType, 18 );
+    my $d = $doca->adoptNode($b);
+
+    ok( $d->isSameNode( $b ) );
+    my @attrb = $d->attributes;
+    ok( scalar(@attrb), 1 );
+    ok( $attrb[0]->nodeType, 18 );
 }