Commits

ph...@9ae0c189-cd1f-4510-a509-f4891f5cf20d  committed e7ca747

Modified Files:
Changes
+ version notes

LibXML.xs
+ several whitespace diffes and error checking

perl-libxml-sax.c
- memleaks
+ namespace handling

perl-libxml-mm.c
- memleaks

lib/XML/LibXML/SAX/Builder.pm
+ CDATA fixes

t/02parse.t t/11memory.t
+ tons of new tests

  • Participants
  • Parent commits 73c3e4a

Comments (0)

Files changed (7)

    - fixed default iterator of XML::LibXML::Iterator
    - interface for raw libxml2 DOM building functions 
      (currently just addChild(), others will follow)
-   - fixed memory leak in XML::LibXML::SAX (almost not leaking)
+   - fixed memory leak in XML::LibXML::SAX
+   - fixed memory leak in push parser code
    - fixed namespace handling if nodes are imported to a new DOM.
    - fixed segmentation fault during validation
+   - fixed bad CDATA handing in XML::LibXML::SAX::Builder
+   - fixed namespace handing in XML::LibXML::SAX
+   - fixed attribute handing in XML::LibXML::SAX
    - more documentation 
 
 1.53
        
         PmmSAXInitContext( ctxt, self );
 
-        xmlFree(ctxt->sax);
-        ctxt->sax = PSaxGetHandler();
-
         RETVAL = xmlParseDocument(ctxt);
 
-        xmlFree( ctxt->sax );
-        ctxt->sax = NULL;
         PmmSAXCloseContext(ctxt);
         xmlFreeParserCtxt(ctxt);
 
         
         xmlParseDocument(ctxt);
 
-        xmlFree(ctxt->sax);
-        ctxt->sax = NULL;
         PmmSAXCloseContext(ctxt);
         xmlFreeParserCtxt(ctxt);
                 
             croak("Could not create file parser context for file '%s' : %s", filename, strerror(errno));
         }
 
-        ctxt->sax = PSaxGetHandler();
         PmmSAXInitContext( ctxt, self );
 
         docbParseDocument(ctxt);
 
-        xmlFree(ctxt->sax);
-        ctxt->sax = NULL;
         PmmSAXCloseContext(ctxt);
         xmlFreeParserCtxt(ctxt);
                 
                 croak("Couldn't create memory parser context: %s", strerror(errno));
             }   
             PmmSAXInitContext( ctxt, self );         
-            ctxt->sax = PSaxGetHandler();
 
             LibXML_init_parser(self);
             handler = PSaxGetHandler();
     CODE:
         /* create empty context */
         LibXML_init_parser(self);
+        ctxt = xmlCreatePushParserCtxt( NULL, NULL, NULL, 0, NULL );
+
         if ( with_sax == 1 ) {
-            ctxt = xmlCreatePushParserCtxt( PSaxGetHandler(),
-                                            NULL,
-                                            NULL,
-                                            0,
-                                            NULL );
             PmmSAXInitContext( ctxt, self );
         }
-        else {
-            ctxt = xmlCreatePushParserCtxt( NULL, NULL, NULL, 0, NULL );
-        }
+        LibXML_cleanup_callbacks();
+        LibXML_cleanup_parser(); 
         sv_2mortal(LibXML_error);
 
         RETVAL = PmmContextSv( ctxt );
         RETVAL
 
 int
-_push( self, pctxt, data ) 
+_push( self, pctxt, data )
         SV * self
         SV * pctxt
         SV * data
             xs_warn( "empty string" );
             XSRETURN_UNDEF;
         }
-
-        LibXML_init_error();
-        
+/*        LibXML_init_error(); */
+        LibXML_init_parser(self);
         xmlParseChunk(ctxt, chunk, len, 0);
-
         LibXML_cleanup_callbacks();
-        LibXML_cleanup_parser();    
-
+        LibXML_cleanup_parser();
         sv_2mortal(LibXML_error); 
 
         RETVAL = 1;
         }
     CODE:
         PmmNODE( SvPROXYNODE( pctxt ) ) = NULL;
-
-        LibXML_init_error();
-        /* LibXML_init_parser(self); */
-
+        LibXML_init_parser(self); 
         xmlParseChunk(ctxt, "", 0, 1); /* finish the parse */
         LibXML_cleanup_callbacks();
-        LibXML_cleanup_parser();    
-
+        LibXML_cleanup_parser();
         sv_2mortal(LibXML_error);
-
-
         if ( ctxt->node != NULL && restore == 0 ) {
             xmlFreeParserCtxt(ctxt);            
             LibXML_croak_error();
         }
     CODE:
         PmmNODE( SvPROXYNODE( pctxt ) ) = NULL;
-
-        LibXML_init_error();
-        /* LibXML_init_parser(self); */
+        LibXML_init_parser(self); 
         xmlParseChunk(ctxt, "", 0, 1); /* finish the parse */
+
         LibXML_cleanup_callbacks();
         LibXML_cleanup_parser();    
-
-        sv_2mortal(LibXML_error);
+        sv_2mortal(LibXML_error); 
 
         PmmSAXCloseContext(ctxt);
-
-        xmlFree(ctxt->sax);
-        ctxt->sax = NULL;
         xmlFreeParserCtxt(ctxt);
         XSRETURN_UNDEF;
 
         xmlNodePtr nNode
     PREINIT:
         xmlNodePtr retval = NULL;
+        ProxyNodePtr proxy;
     CODE:
         xmlUnlinkNode(nNode);
+        proxy = PmmPROXYNODE(nNode);
         retval = xmlAddChild( self, nNode );
 
+        if ( retval == NULL ) {
+            croak( "ERROR!\n" );
+        }
+
+        if ( retval != nNode ) {
+            xs_warn( "node was lost during operation\n" );
+            PmmNODE(proxy) = NULL;
+        }
+
         RETVAL = PmmNodeToSv( retval,
                               PmmOWNERPO(PmmPROXYNODE(self)) );
         if ( retval != self ) {

File lib/XML/LibXML/SAX/Builder.pm

     $self->{Parent} = $self->{Parent}->parentNode();
 }
 
+sub start_cdata {
+    my $self = shift;
+    $self->{IN_CDATA} = 1;
+}
+
+sub end_cdata {
+    my $self = shift;
+    $self->{IN_CDATA} = 0;
+}
+
 sub characters {
     my ($self, $chars) = @_;
     if ( not defined $self->{DOM} and not defined $self->{Parent} ) {
     }
     return unless $self->{Parent};
     my $node;
+
+    unless ( defined $chars and defined $chars->{Data} ) {
+        return;
+    }
+
     if ( defined $self->{DOM} ) {
-        $node = $self->{DOM}->createTextNode($chars->{Data});
+        if ( defined $self->{IN_CDATA} and $self->{IN_CDATA} == 1 ) {
+            $node = $self->{DOM}->createCDATASection($chars->{Data});
+        }
+        else {
+            $node = $self->{DOM}->createTextNode($chars->{Data});
+        }
+    }
+    elsif ( defined $self->{IN_CDATA} and $self->{IN_CDATA} == 1 ) {
+        $node = XML::LibXML::CDATASection->new($chars->{Data});
     }
     else {
         $node = XML::LibXML::Text->new($chars->{Data});
         $self->{NamespaceStack}->push_context;
     }
 
+    unless ( defined $chars and defined $chars->{Data} ) {
+        return;
+    }
+
     if ( defined $self->{DOM} ) {
         $comment = $self->{DOM}->createComment( $chars->{Data} );
     }

File perl-libxml-mm.c

 {
     ProxyNodePtr proxy = NULL;
 
+    if ( node == NULL ) {
+        warn( "no node found\n" );
+        return NULL;
+    }
+
     if ( node->_private == NULL ) {
-        proxy = (ProxyNodePtr)malloc(sizeof(ProxyNode));
-        /* proxy = (ProxyNodePtr)Newz(0, proxy, 0, ProxyNode); */
+        proxy = (ProxyNodePtr)malloc(sizeof(struct _ProxyNode)); 
+        /* proxy = (ProxyNodePtr)Newz(0, proxy, 0, ProxyNode);  */
         if (proxy != NULL) {
             proxy->node  = node;
             proxy->owner   = NULL;
             libnode = PmmNODE( node );
             if ( libnode != NULL ) {
                 if ( libnode->_private != node ) {
+                    warn( "lost node\n" );
                     libnode = NULL;
                 }
                 else {
                 
                 PmmFreeNode( libnode );
             }
+            /* Safefree( node ); */
             free( node );
         }
     }
 {
     ProxyNodePtr proxy = NULL;
 
-    if ( node->_private == NULL ) {
-        proxy = (ProxyNodePtr)malloc(sizeof(ProxyNode));
-        if (proxy != NULL) {
-            proxy->node  = (xmlNodePtr)node;
-            proxy->owner   = NULL;
-            proxy->count   = 0;
-            node->_private = (void*) proxy;
-        }
+    proxy = (ProxyNodePtr)xmlMalloc(sizeof(ProxyNode));
+    if (proxy != NULL) {
+        proxy->node  = (xmlNodePtr)node;
+        proxy->owner   = NULL;
+        proxy->count   = 1;
     }
     else {
-        proxy = (ProxyNodePtr)node->_private;
+        warn( "empty context" );
     }
     return proxy;
 }
             xs_warn( "NODE DELETATION\n" );
             libnode = (xmlParserCtxtPtr)PmmNODE( node );
             if ( libnode != NULL ) {
+                free( libnode->_private );
                 libnode->_private = NULL;
-                PmmNODE( node ) = NULL;
+                PmmNODE( node )   = NULL;
                 xmlFreeParserCtxt(libnode);
             }
-            free( node );
         }
+        xmlFree( node );
     }
     return retval;
 }
     ProxyNodePtr dfProxy= NULL;
     SV * retval = &PL_sv_undef;
     const char * CLASS = "XML::LibXML::ParserContext";
+    void * saxvector = NULL;
 
     if ( ctxt != NULL ) {
         dfProxy = PmmNewContext(ctxt);
             }
 
             /* retval = C2Sv( decoded, real_doc->encoding ); */
-            /* xmlFree( decoded ); */
+            xmlFree( decoded );
         }
         else {
             retval = newSVpvn( (const char *)string, xmlStrlen(string) );
     if ( refnode != NULL ) {
         xmlDocPtr real_dom = refnode->doc;
         xs_warn("have node!");
-        if (real_dom != NULL &&real_dom->encoding != NULL ) {
+        if (real_dom != NULL && real_dom->encoding != NULL ) {
             xs_warn("encode string!");
             /*  speed things a bit up.... */
             if ( scalar != NULL && scalar != &PL_sv_undef ) {

File perl-libxml-sax.c

 #endif
 
 #define NSDELIM ':'
-#define NSDEFAULTURI "http://www.w3.org/XML/1998/namespace"
-
+/* #define NSDEFAULTURI "http://www.w3.org/XML/1998/namespace" */ 
+#define NSDEFAULTURI "http://www.w3.org/2000/xmlns/"
 typedef struct {
     SV * parser;
     xmlNodePtr ns_stack;
     STRLEN len;
 
     if ( string != NULL ) {
-        len = xmlStrlen( string );
-        retval = newSVpvn( (const char *)string, len );
+        xmlChar * str = xmlStrdup( string );
+        len = xmlStrlen( str );
+        retval = NEWSV(0, len+1); 
+        sv_setpvn(retval, str, len );
 #ifdef HAVE_UTF8
         SvUTF8_on( retval );
 #endif
+        xmlFree( str );
+    }
 
-    }
     return retval;
 }
 
     PERL_HASH(EncodingHash,   "Encoding",      8);
 }
 
+xmlSAXHandlerPtr PSaxGetHandler();
+
+
 void
 PmmSAXInitContext( xmlParserCtxtPtr ctxt, SV * parser )
 {
     dTHX;
 
     vec = (PmmSAXVector*) xmlMalloc( sizeof(PmmSAXVector) );
+
     vec->ns_stack_root = xmlNewDoc(NULL);
     vec->ns_stack      = xmlNewDocNode(vec->ns_stack_root,
                                        NULL,
 
     vec->locator = NULL;
 
-    SvREFCNT_inc( parser );
-    vec->parser  = parser;
+    vec->parser  = SvREFCNT_inc( parser );
     th = hv_fetch( (HV*)SvRV(parser), "HANDLER", 7, 0 );
     if ( th != NULL && SvTRUE(*th) ) {
-        vec->handler = newSVsv(*th)  ;
+        vec->handler = SvREFCNT_inc(*th)  ;
     }
     else {
         vec->handler = NULL  ;
     }
 
+    if ( ctxt->sax ) {
+        xmlFree( ctxt->sax );
+    }
+    ctxt->sax = PSaxGetHandler();
+
     ctxt->_private = (void*)vec;
 }
 
     PmmSAXVector * vec = (PmmSAXVectorPtr) ctxt->_private;
     dTHX;
     
-    if ( vec->handler ) {
+    if ( vec->handler != NULL ) {
         SvREFCNT_dec( vec->handler );
-        vec->handler = NULL;
     }
+
+    xmlFree( ctxt->sax );
+    ctxt->sax = NULL;
+
     SvREFCNT_dec( vec->parser );
 
     xmlFreeDoc( vec->ns_stack_root );
+    
     xmlFree( vec );
 }
 
     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);
     }
     PUSHMARK(SP) ;
     XPUSHs(handler);
 
-
     rv = newRV_noinc((SV*)param);
 
     XPUSHs(rv);
                  _C2Sv(prefix, NULL), PrefixHash);
     }
     else {
-/*         warn("null prefix!\n" ); */
         hv_store(param, "Prefix", 6,
                  _C2Sv("", NULL), PrefixHash);
     }
 
 void 
 PmmExtendNsStack( PmmSAXVectorPtr sax , const xmlChar * name) {
-    xmlNodePtr newNS = xmlNewDocNode( sax->ns_stack_root, NULL, name, NULL );
-    xmlAddChild(sax->ns_stack, newNS);
-    sax->ns_stack = newNS;
+    xmlNodePtr newNS = NULL;
+    xmlChar * localname = NULL;
+    xmlChar * prefix = NULL;
+    
+    localname = xmlSplitQName( NULL, name, &prefix );
+    if ( prefix != NULL ) {
+        /* check if we can find a namespace with that prefix... */
+        xmlNsPtr ns = xmlSearchNs( sax->ns_stack->doc, sax->ns_stack, prefix );
+
+        if ( ns != NULL ) {
+            newNS = xmlNewDocNode( sax->ns_stack_root, ns, localname, NULL );
+        }
+        else {
+            newNS = xmlNewDocNode( sax->ns_stack_root, NULL, name, NULL );
+        }
+    }
+    else {
+        newNS = xmlNewDocNode( sax->ns_stack_root, NULL, name, NULL );
+    }
+
+    if ( newNS != NULL ) {
+        xmlAddChild(sax->ns_stack, newNS);
+        sax->ns_stack = newNS;
+    }
+
+    if ( localname != NULL ) {
+        xmlFree( localname ) ;
+    }
+    if ( prefix != NULL ) {
+        xmlFree( prefix );
+    }
 }
 
 void
 {
     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 );
         }
         return;
     }
 
-    localname = xmlSplitQName( NULL, sax->ns_stack->name, &prefix );
+    ns = xmlNewNs( sax->ns_stack, href, name );         
 
-    ns = xmlNewNs( sax->ns_stack, href, name );         
-    PSaxStartPrefix( sax, name, href, handler );
+    if ( sax->ns_stack->ns == NULL ) {
+        localname = xmlSplitQName( NULL, sax->ns_stack->name, &prefix );
 
-    if ( name != NULL ) {
-        if ( sax->ns_stack->ns == NULL
-             && xmlStrEqual( prefix , name ) ) {
+        if ( name != NULL ) {
+            if ( xmlStrEqual( prefix , name ) ) {
+                xmlChar * oname = (xmlChar*)(sax->ns_stack->name);
+                sax->ns_stack->ns = ns;
+                xmlFree( oname );
+                sax->ns_stack->name = (const xmlChar*) xmlStrdup( localname );
+            }
+        }
+        else if ( prefix == NULL ) {
             sax->ns_stack->ns = ns;
-            xmlFree( (xmlChar*) sax->ns_stack->name );
-            sax->ns_stack->name = (const xmlChar*) xmlStrdup( localname );
         }
     }
-    else if ( prefix == NULL && sax->ns_stack->ns == NULL) {
-        sax->ns_stack->ns = ns;
+
+    if ( prefix ) {
+        xmlFree( prefix );
     }
-    xmlFree( prefix );
-    xmlFree( localname );
+    if ( localname ) {
+        xmlFree( localname );
+    }
+
+    PSaxStartPrefix( sax, name, href, handler );
 }
 
 HV *
     SV * tmp;
 
     xmlNsPtr ns = NULL;
+
     if ( name != NULL && xmlStrlen( name )  ) {
-        xmlChar *localname = NULL, *prefix = NULL;
         hv_store(retval, "Name", 4,
                  _C2Sv(name, NULL), NameHash);
 
         if ( sax->ns_stack->ns != NULL ) {  
             ns = sax->ns_stack->ns;
-/*             warn("found 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,
-                         tmp, PrefixHash);
+                         _C2Sv("",NULL), PrefixHash);
             }
 
             hv_store(retval, "LocalName", 9,
         }
         else {
             hv_store(retval, "NamespaceURI", 12,
-                     tmp, NsURIHash);
+                     _C2Sv("",NULL), NsURIHash);
             hv_store(retval, "Prefix", 6,
-                     SvREFCNT_inc(tmp), PrefixHash);
+                     _C2Sv("",NULL), PrefixHash);
             hv_store(retval, "LocalName", 9,
                      _C2Sv(name, NULL), LocalNameHash);
         }
         return NULL;
     }
     namelen = xmlStrlen( name );
-    if ( nsURI != NULL ) {
-        urilen = xmlStrlen( nsURI );
-    }
 
     retval =xmlStrncat( retval, "{",1 );
     if ( nsURI != NULL ) {
+        urilen = xmlStrlen( nsURI );
         retval =xmlStrncat( retval, nsURI, urilen );
     } 
     retval = xmlStrncat( retval, "}",1 );
     retval = newHV();
 
     if ( ta != NULL ) {
-
         while ( *ta != NULL ) {
             atV = newHV();
             name = *ta;  ta++;
                 if ( xmlStrEqual( "xmlns", name ) ) {
                     /* a default namespace */
                     PmmAddNamespace( sax, NULL, value, handler);  
-                    nsURI = "http://www.w3.org/2000/xmlns/";
+                    nsURI = NSDEFAULTURI;
 
                     hv_store(atV, "Prefix", 6,
                              _C2Sv(name, NULL), PrefixHash);
                     hv_store(atV, "LocalName", 9,
                              _C2Sv("",NULL), LocalNameHash);
                     hv_store(atV, "NamespaceURI", 12,
-                             _C2Sv("http://www.w3.org/2000/xmlns/",NULL),
+                             _C2Sv(NSDEFAULTURI,NULL),
                              NsURIHash);
                     
                 }
                                      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(nsURI,NULL),
+                             _C2Sv(NSDEFAULTURI,NULL),
                              NsURIHash);
-                    xmlFree( prefix );
                 }
                 else if ( ns = PmmGetNsMapping( sax->ns_stack, prefix ) ) {
                     localname = xmlSplitQName(NULL, name, &prefix);        
                              _C2Sv(ns->prefix, NULL), PrefixHash);
                     hv_store(atV, "LocalName", 9,
                              _C2Sv(localname, NULL), LocalNameHash);
-                    xmlFree( prefix );
                 }
                 else {
                     hv_store(atV, "NamespaceURI", 12,
                              _C2Sv(name, NULL), LocalNameHash);
                 }
 
-                keyname = PmmGenNsName( localname!= NULL ? localname: name,
+                keyname = PmmGenNsName( localname != NULL ? localname : name,
                                         nsURI );
 
                 len = xmlStrlen( keyname );
                          newRV_noinc((SV*)atV),
                          atnameHash );
 
-                xmlFree( keyname );
-                xmlFree(localname);
+                if ( keyname != NULL ) {
+                    xmlFree( keyname );
+                }
+                if ( localname != NULL ) {
+                    xmlFree(localname);
+                }
+                localname = NULL;
+                if ( prefix != NULL ) {
+                    xmlFree( prefix );
+                }
+                prefix    = NULL;
+
             }            
         }
     }
     PmmSAXVectorPtr sax   = (PmmSAXVectorPtr)ctxt->_private;
     int count             = 0;
     dTHX;
-    HV* real_obj          = (HV *)SvRV(sax->parser);
-    HV* empty             = newHV();
+    HV* empty;
     SV * handler         = sax->handler;
 
     SV * rv;
-
     if ( handler != NULL ) {
+       
         dSP;
         
         ENTER;
         SAVETMPS;
         
+        empty = newHV();
         PUSHMARK(SP) ;
         XPUSHs(handler);
-        XPUSHs(sv_2mortal(newRV_inc((SV*)empty)));
+        XPUSHs(sv_2mortal(newRV_noinc((SV*)empty)));
         PUTBACK;
         
         count = perl_call_method( "start_document", 0 );
         
         SPAGAIN;
-        
+
         PUSHMARK(SP) ;
 
     
         XPUSHs(handler);
 
-
+        empty = newHV();
         if ( ctxt->version != NULL ) {
             hv_store(empty, "Version", 7,
                      _C2Sv(ctxt->version, NULL), VersionHash);
             hv_store(empty, "Encoding", 8,
                      _C2Sv(ctxt->encoding, NULL), EncodingHash);
         }
+
         rv = newRV_noinc((SV*)empty);
         XPUSHs( rv);
 
     int count             = 0;
     dTHX;
     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;
 
     count = perl_call_method( "start_element", 0 );
     
     sv_2mortal(rv) ;
-
     FREETMPS ;
     LEAVE ;
 
     PmmSAXVectorPtr  sax  = (PmmSAXVectorPtr)ctxt->_private;
     dTHX;
     int count;
-/*     HV* real_obj          = (HV *)SvRV(sax->parser); */
     SV * handler         = sax->handler;
     SV * rv;
     HV * element;
     PmmSAXVectorPtr sax = (PmmSAXVectorPtr)ctxt->_private;
     int count = 0;
     dTHX;
-    HV* real_obj = (HV *)SvRV(sax->parser);
     HV* element;
-    SV * handler = sax->handler;
-    
+    SV * handler;
     SV * rv = NULL;
 
+    if ( sax == NULL ) {
+/*         warn( "lost my sax context!? ( %s, %d )\n", ch, len ); */
+        return 0;
+    }
+
+    handler = sax->handler;
+
     if ( ch != NULL && handler != NULL ) {
         xmlChar * data = xmlStrndup( ch, len );
 
         SAVETMPS;
 
         PUSHMARK(SP) ;
+
         XPUSHs(handler);
         element = PmmGenCharDataSV(aTHX_ sax,data);
         rv = newRV_noinc((SV*)element);
     PmmSAXVectorPtr sax = (PmmSAXVectorPtr)ctxt->_private;
     int count = 0;
     dTHX;
-    HV* real_obj = (HV *)SvRV(sax->parser);
     HV* element;
     SV * handler = sax->handler;
     
     PmmSAXVectorPtr sax = (PmmSAXVectorPtr)ctxt->_private;
     int count = 0;
     dTHX;
-    HV* real_obj = (HV *)SvRV(sax->parser);
+
     HV* element;
     SV * handler = sax->handler;
     
 
         PUSHMARK(SP) ;
         XPUSHs(handler);
+        PUTBACK;
+        count = perl_call_method( "start_cdata", 0 );
+
+        SPAGAIN;        
+        PUSHMARK(SP) ;
+    
+        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 );
+        count = perl_call_method( "characters", 0 );
+
+        SPAGAIN;        
+        PUSHMARK(SP) ;
+    
+        XPUSHs(handler);
+        PUTBACK;
+
+        count = perl_call_method( "end_cdata", 0 );
 
         sv_2mortal(rv);
 
     PmmSAXVectorPtr sax   = (PmmSAXVectorPtr)ctxt->_private;
     int count             = 0;
     dTHX;
-    HV* real_obj          = (HV *)SvRV(sax->parser);
     HV* empty             = newHV();
-    SV * handler         = sax->handler;
+    SV * handler          = sax->handler;
 
     SV * element;
     SV * rv = NULL;
     dTHX;
     dSP;
 
+    ENTER;
+    SAVETMPS;
+
+    PUSHMARK(SP) ;
+
+    XPUSHs(sax->parser);
+
     svMessage = NEWSV(0,512);
 
     va_start(args, msg);
     sv_vsetpvfn(svMessage, msg, xmlStrlen(msg), &args, NULL, 0, NULL);
     va_end(args);
 
-
-    ENTER;
-    SAVETMPS;
-
-    PUSHMARK(SP) ;
-    XPUSHs(sax->parser);
-
     XPUSHs(sv_2mortal(svMessage));
     XPUSHs(sv_2mortal(newSViv(ctxt->input->line)));
     XPUSHs(sv_2mortal(newSViv(ctxt->input->col)));
 use Test;
 use IO::File;
 
-BEGIN { plan tests => 42 };
+BEGIN { plan tests => 351};
 use XML::LibXML;
 use XML::LibXML::Common qw(:libxml);
+use XML::LibXML::SAX;
+use XML::LibXML::SAX::Builder;
+
+use constant XML_DECL => "<?xml version=\"1.0\"?>\n";
 
 ##
 # test values
-my $goodWFString = "<foobar/>";
-my $badWFString1 = "<foo>&</foo>";
-my $badWFString2 = "<foo>";
-my $badWFString3 = '<?xml version="1.0">';
+my @goodWFStrings = (
+'<foobar/>',
+'<foobar></foobar>',
+XML_DECL . "<foobar></foobar>",
+'<?xml version="1.0" encoding="UTF8"?>'."\n<foobar></foobar>",
+'<?xml version="1.0" encoding="ISO-8859-1"?>'."\n<foobar></foobar>",
+XML_DECL. "<foobar> </foobar>\n",
+XML_DECL. '<foobar><foo/></foobar> ',
+XML_DECL. '<foobar> <foo/> </foobar> ',
+XML_DECL. '<foobar><![CDATA[<>&"\']]></foobar>',
+XML_DECL. '<foobar>&lt;&gt;&amp;&quot;&apos;</foobar>',
+XML_DECL. '<foobar>&#x20;&#160;</foobar>',
+XML_DECL. '<!--comment--><foobar>foo</foobar>',
+XML_DECL. '<foobar>foo</foobar><!--comment-->',
+XML_DECL. '<foobar>foo<!----></foobar>',
+XML_DECL. '<foobar foo="bar"/>',
+XML_DECL. '<foobar foo="\'bar>"/>',
+XML_DECL. '<bar:foobar foo="bar"><bar:foo/></bar:foobar>',
+                    );
 
-my $goodWBString = "foo<bar/>foo";
-my $badWBString1 = "<foo>bar";
-my $badWBString2 = "foo</bar>";
+my @goodWFNSStrings = (
+XML_DECL. '<foobar xmlns:bar="foo" bar:foo="bar"/>',
+XML_DECL. '<foobar xmlns="foo" foo="bar"><foo/></foobar>',
+XML_DECL. '<bar:foobar xmlns:bar="foo" foo="bar"><bar:foo/></bar:foobar>',
+XML_DECL. '<bar:foobar xmlns:bar="foo" foo="bar"><foo/></bar:foobar>',
+XML_DECL. '<bar:foobar xmlns:bar="foo" bar:foo="bar"><bar:foo/></bar:foobar>',
+                      );
+
+my @goodWFDTDStrings = (
+XML_DECL. '<!DOCTYPE foobar ['."\n".'<!ENTITY foo " test ">'."\n".']>'."\n".'<foobar>&foo;</foobar>',
+XML_DECL. '<!DOCTYPE foobar [<!ENTITY foo "bar">]><foobar>&foo;</foobar>',
+XML_DECL. '<!DOCTYPE foobar [<!ENTITY foo "bar">]><foobar>&foo;&gt;</foobar>',
+XML_DECL. '<!DOCTYPE foobar [<!ENTITY foo "bar=&quot;foo&quot;">]><foobar>&foo;&gt;</foobar>',
+XML_DECL. '<!DOCTYPE foobar [<!ENTITY foo "bar">]><foobar>&foo;&gt;</foobar>',
+XML_DECL. '<!DOCTYPE foobar [<!ENTITY foo "bar">]><foobar foo="&foo;"/>',
+XML_DECL. '<!DOCTYPE foobar [<!ENTITY foo "bar">]><foobar foo="&gt;&foo;"/>',
+                       );
+
+my @badWFStrings = (
+"",                                        # totally empty document
+XML_DECL,                                  # only XML Declaration
+"<!--ouch-->",                             # comment only is like an empty document 
+'<!DOCTYPE ouch [<!ENTITY foo "bar">]>',   # no good either ...
+"<ouch>",                                  # single tag (tag mismatch)
+"<ouch/>foo",                              # trailing junk
+"foo<ouch/>",                              # leading junk
+"<ouch foo=bar/>",                         # bad attribute
+'<ouch foo="bar/>',                        # bad attribute
+"<ouch>&</ouch>",                          # bad char
+"<ouch>&#0x20;</ouch>",                    # bad char
+"<foob�r/>",                               # bad encoding
+"<ouch>&foo;</ouch>",                      # undefind entity
+"<ouch>&gt</ouch>",                        # unterminated entity
+XML_DECL. '<!DOCTYPE foobar [<!ENTITY foo "bar">]><foobar &foo;="ouch"/>',          # bad placed entity
+XML_DECL. '<!DOCTYPE foobar [<!ENTITY foo "bar=&quot;foo&quot;">]><foobar &foo;/>', # even worse 
+"<ouch><!---></ouch>",                     # bad comment
+'<ouch><!-----></ouch>',                   # bad either... (is this conform with the spec????)
+                    );
+
+my @goodWBStrings = (
+" ",
+"<!--good-->",
+"<![CDATA[>&<]]>",
+"foo<bar/>foo",
+"foo<bar/>",
+"<bar/>foo",
+"&gt;&#160;",
+'<foo bar="&gt;"/>',
+'<foo/>&gt;',
+'<foo/><bar/>',
+'<bar:foobar xmlns:bar="foo" bar:foo="bar"/><foo/>',
+                    );
+
+my @badWBStrings = (
+"",
+"<ouch>",
+"<ouch>bar",
+"bar</ouch>",
+"<ouch/>&foo;", # undefined entity
+"&",            # bad char
+"h�h?",         # bad encoding
+"<!--->",       # bad stays bad ;)
+"<!----->",     # bad stays bad ;)
+);
+
+
+    my %goodPushWF = (
+single1 => ['<foobar/>'],
+single2 => ['<foobar>','</foobar>'],
+single3 => [ XML_DECL, "<foobar>", "</foobar>" ],
+single4 => ["<foo", "bar/>"],
+single5 => ["<", "foo","bar", "/>"],
+single6 => ['<?xml version="1.0" encoding="UTF8"?>',"\n<foobar/>"],
+single7 => ['<?xml',' version="1.0" ','encoding="UTF8"?>',"\n<foobar/>"],
+single8 => ['<foobar', ' foo=', '"bar"', '/>'],
+single9 => ['<?xml',' versio','n="1.0" ','encodi','ng="U','TF8"?>',"\n<foobar/>"],
+multiple1 => [ '<foobar>','<foo/>','</foobar> ', ],
+multiple2 => [ '<foobar','><fo','o','/><','/foobar> ', ],
+multiple3 => [ '<foobar>','<![CDATA[<>&"\']]>','</foobar>'],
+multiple4 => [ '<foobar>','<![CDATA[', '<>&', ']]>', '</foobar>' ],
+multiple5 => [ '<foobar>','<!','[CDA','TA[', '<>&', ']]>', '</foobar>' ],
+multiple6 => ['<foobar>','&lt;&gt;&amp;&quot;&apos;','</foobar>'],
+multiple6 => ['<foobar>','&lt',';&','gt;&a','mp;','&quot;&ap','os;','</foobar>'],
+multiple7 => [ '<foobar>', '&#x20;&#160;','</foobar>' ],
+multiple8 => [ '<foobar>', '&#x','20;&#1','60;','</foobar>' ],
+multiple9 => [ '<foobar>','moo','moo','</foobar> ', ],
+multiple10 => [ '<foobar>','moo','</foobar> ', ],
+comment1  => [ '<!--comment-->','<foobar/>' ],
+comment2  => [ '<foobar/>','<!--comment-->' ],
+comment3  => [ '<!--','comment','-->','<foobar/>' ],
+comment4  => [ '<!--','-->','<foobar/>' ],
+comment5  => [ '<foobar>fo','o<!---','-><','/foobar>' ],
+attr1     => [ '<foobar',' foo="bar"/>'],
+attr2     => [ '<foobar',' foo','="','bar','"/>'],
+attr3     => [ '<foobar',' fo','o="b','ar"/>'],
+prefix1   => [ '<bar:foobar/>' ],
+prefix2   => [ '<bar',':','foobar/>' ],
+prefix3   => [ '<ba','r:fo','obar/>' ],
+ns1       => [ '<foobar xmlns:bar="foo"/>' ],
+ns2       => [ '<foobar ','xmlns:bar="foo"','/>' ],
+ns3       => [ '<foo','bar x','mlns:b','ar="foo"/>' ],
+ns4       => [ '<bar:foobar xmlns:bar="foo"/>' ],
+ns5       => [ '<bar:foo','bar xm','lns:bar="fo','o"/>' ],
+ns6       => [ '<bar:fooba','r xm','lns:ba','r="foo"','><bar',':foo/','></bar'.':foobar>'],
+dtd1      => [XML_DECL, '<!DOCTYPE ','foobar [','<!ENT','ITY foo " test ">',']>','<foobar>&f','oo;</foobar>',],
+dtd2      => [XML_DECL, '<!DOCTYPE ','foobar [','<!ENT','ITY foo " test ">',']>','<foobar>&f','oo;&gt;</foobar>',],
+                    );
 
 my $goodfile = "example/dromeds.xml";
 my $badfile1 = "example/bad.xml";
 my $badfile2 = "does_not_exist.xml";
 
+
 my $parser = XML::LibXML->new();
 
-print "# 1. Well Formed String Parsing\n";
+print "# 1 NON VALIDATING PARSER\n";
+print "# 1.1 WELL FORMED STRING PARSING\n";
+print "# 1.1.1 DEFAULT VALUES\n";
 
 {
-    my $doc = $parser->parse_string($goodWFString);
-    ok(defined $doc);
-    my $str = $doc->toString();
-    $str =~ s/\<\?xml[^\?]*\?\>//;
-    $str =~ s/\n//g;
-    ok($str, $goodWFString );    
+    foreach my $str ( @goodWFStrings,@goodWFNSStrings,@goodWFDTDStrings ) {
+        my $doc = $parser->parse_string($str);
+        ok($doc);
+    }
 }
 
-eval { my $fail = $parser->parse_string($badWFString1); };
-ok($@);
-
-eval { my $fail = $parser->parse_string($badWFString2); };
-ok($@);
-
-eval { my $fail = $parser->parse_string($badWFString3); };
-ok($@);
-
-
-eval { my $fail = $parser->parse_string(""); };
-ok($@);
-
 eval { my $fail = $parser->parse_string(undef); };
 ok($@);
 
-print "# 2. Well Ballanced String Parsing\n";
+foreach my $str ( @badWFStrings ) {
+    eval { my $fail = $parser->parse_string($str); };  
+    ok($@);
+}
+
+
+print "# 1.1.2 NO KEEP BLANKS\n";
+
+$parser->keep_blanks(0);
 
 {
-    my $fragment;
-    eval { $fragment = $parser->parse_xml_chunk( $goodWBString ); };
-    ok( $fragment );
-    ok( $fragment->toString(), $goodWBString );
+    foreach my $str ( @goodWFStrings,@goodWFNSStrings,@goodWFDTDStrings ) {
+        my $doc = $parser->parse_string($str);
+        ok($doc);
+    }
 }
 
-eval { my $fail = $parser->parse_xml_chunk($badWBString1); };
+eval { my $fail = $parser->parse_string(undef); };
 ok($@);
 
-eval { my $fail = $parser->parse_xml_chunk($badWBString2); };
+foreach my $str ( @badWFStrings ) {
+    eval { my $fail = $parser->parse_string($str); };  
+    ok($@);
+}
+
+$parser->keep_blanks(1);
+
+print "# 1.1.3 EXPAND ENTITIES\n";
+
+$parser->expand_entities(0);
+
+{
+    foreach my $str ( @goodWFStrings,@goodWFNSStrings,@goodWFDTDStrings ) {
+        my $doc = $parser->parse_string($str);
+        ok($doc);
+    }
+}
+
+eval { my $fail = $parser->parse_string(undef); };
 ok($@);
 
-eval { my $fail = $parser->parse_xml_chunk(""); };
+foreach my $str ( @badWFStrings ) {
+    eval { my $fail = $parser->parse_string($str); };  
+    ok($@);
+}
+
+$parser->expand_entities(1);
+
+print "# 1.1.4 PEDANTIC\n";
+
+$parser->pedantic_parser(1);
+
+{
+    foreach my $str ( @goodWFStrings,@goodWFNSStrings,@goodWFDTDStrings ) {
+        my $doc = $parser->parse_string($str);
+        ok($doc);
+    }
+}
+
+eval { my $fail = $parser->parse_string(undef); };
+ok($@);
+
+foreach my $str ( @badWFStrings ) {
+    eval { my $fail = $parser->parse_string($str); };  
+    ok($@);
+}
+
+$parser->pedantic_parser(0);
+
+
+
+print "# 1.2 WELL BALLANCED STRING PARSING\n";
+
+print "# 1.2.1 DEFAULT VALUES\n";
+{
+    foreach my $str ( @goodWBStrings ) {
+        my $fragment = $parser->parse_xml_chunk($str);
+        ok($fragment);
+    }
+}
+
+eval { my $fail = $parser->parse_xml_chunk(undef); };
 ok($@);
 
 eval { my $fail = $parser->parse_xml_chunk(undef); };
 ok($@);
 
-print "# 3. Parse A File\n";
+foreach my $str ( @badWBStrings ) {
+    eval { my $fail = $parser->parse_xml_chunk($str); };  
+    ok($@);
+}
+
+
+print "# 1.3 PARSE A FILE\n";
 
 {
     my $doc = $parser->parse_file($goodfile);
     $XML::LibXML::skipXMLDeclaration = 0;
 }
 
-print "# 4. Parse A Handle\n";
+print "# 1.4 PARSE A HANDLE\n";
 
 my $fh = IO::File->new($goodfile);
 ok($fh);
     my $doc = $parser->parse_file( "example/dtd.xml" );
     my @cn = $doc->documentElement->childNodes;
     ok( scalar @cn, 1 );
-
+    
     $doc = $parser->parse_file( "example/complex/complex2.xml" );
     @cn = $doc->documentElement->childNodes;
     ok( scalar @cn, 1 );
 
     $parser->expand_entities(0);
+    $doc = $parser->parse_file( "example/dtd.xml" );
+    @cn = $doc->documentElement->childNodes;
+    ok( scalar @cn, 3 );
 }
 
-print "# 5. x-include processing\n";
+print "# 1.5 x-include processing\n";
 
 my $goodXInclude = q{
 <x>
     ok($@);
 }
 
-print "# 6. push parser\n";
+print "# 2 push parser\n";
 
 {
+    foreach my $key ( keys %goodPushWF ) {
+        foreach ( @{$goodPushWF{$key}} ) {
+            $parser->push( $_);
+        }
+
+        my $doc;
+        eval {$doc = $parser->finish_push; };
+        ok($doc && !$@);                    
+    }
+
     my @good_strings = ("<foo>", "bar", "</foo>" );
     my @bad_strings  = ("<foo>", "bar");
 
     my $parser = XML::LibXML->new;
     {
-        
-        $parser->push( @good_strings );
+        for ( @good_strings ) {        
+            $parser->push( $_ );
+        }
         my $doc = $parser->finish_push;
         ok($doc);
     }
     }
 }
 
-print "# 7. SAX parser\n";
+print "# 3 SAX PARSER\n";
 
 {
-    use XML::LibXML::SAX;
-    use XML::LibXML::SAX::Builder;
     my $handler = XML::LibXML::SAX::Builder->new();
     my $generator = XML::LibXML::SAX->new( Handler=>$handler );
 
-
-    my $string1  = q{<bar>foo</bar>};
-
-    $doc = $generator->parse_string( $string1 );
-    ok( $doc );
-
     my $string  = q{<bar foo="bar">foo</bar>};
 
     $doc = $generator->parse_string( $string );
     ok( $doc );
 
+    print "# 3.1 GENERAL TESTS \n";
+    foreach my $str ( @goodWFStrings ) {
+        my $doc = $generator->parse_string( $str );
+        ok( $doc );
+    }
+
+    print "# CDATA Sections\n";
+
+    $string = q{<foo><![CDATA[&foo<bar]]></foo>};
+    $doc = $generator->parse_string( $string );
+    my @cn = $doc->documentElement->childNodes();
+    ok( scalar @cn );
+    ok( $cn[0]->nodeType, XML_CDATA_SECTION_NODE );
+    ok( $cn[0]->textContent, "&foo<bar" );
+
+    print "# 3.2 NAMESPACE TESTS\n";
+
+    foreach my $str ( @goodWFNSStrings ) {
+        my $doc = $generator->parse_string( $str );
+        ok( $doc );
+    }
+
+    print "# DATA CONSISTENCE\n";    
+    # find out if namespaces are there
     my $string2 = q{<foo xmlns:bar="http://foo.bar">bar<bar:bi/></foo>};
 
     $doc = $generator->parse_string( $string2 );
-    ok($doc);
 
-    my $root = $doc->documentElement;
-    my @attrs = $root->attributes;
+    my @attrs = $doc->documentElement->attributes;
+
     ok( scalar @attrs );
     if ( scalar @attrs ) {
         ok( $attrs[0]->nodeType, XML_NAMESPACE_DECL );
         ok(0);
     }
 
+    print "# 3.3 INTERNAL SUBSETS\n";
+
+    foreach my $str ( @goodWFDTDStrings ) {
+        my $doc = $generator->parse_string( $str );
+        ok( $doc );
+    }
+
+    print "# 3.5 PARSE URI\n"; 
     $doc = $generator->parse_uri( "example/test.xml" );
+    ok($doc);
 
+    print "# 3.6 PARSE CHUNK\n";
+    
+}
+
+print "# 4 SAXY PUSHER\n";
+
+{
+    my $handler = XML::LibXML::SAX::Builder->new();
+    my $parser = XML::LibXML->new;
+
+    $parser->set_handler( $handler );
+    $parser->push( '<foo/>' );
+    my $doc = $parser->finish_push;
     ok($doc);
+
+    foreach my $key ( keys %goodPushWF ) {
+        foreach ( @{$goodPushWF{$key}} ) {
+            $parser->push( $_);
+        }
+
+        my $doc;
+        eval {$doc = $parser->finish_push; };
+        ok($doc);                    
+    }
+}
+
+sub tsub {
+    my $doc = shift;
+
+    my $th = {};
+    $th->{d} = XML::LibXML::Document->createDocument;
+    my $e1  = $th->{d}->createElementNS("x","X:foo");
+
+    $th->{d}->setDocumentElement( $e1 );
+    my $e2 = $th->{d}->createElementNS( "x","X:bar" );
+
+    $e1->appendChild( $e2 );
+
+    $e2->appendChild( $th->{d}->importNode( $doc->documentElement() ) );
+
+    return $th->{d};
 }

File t/11memory.t

 use Test;
 BEGIN { 
     if ($^O eq 'linux' && $ENV{MEMORY_TEST}) {
-        plan tests => 22;
+        plan tests => 24;
     }
     else {
         plan tests => 0;
     }
 }
 use XML::LibXML;
+use XML::LibXML::SAX::Builder;
 {
     if ($^O eq 'linux' && $ENV{MEMORY_TEST}) {
+
         require Devel::Peek;
         my $peek = 0;
     
         ok(1);
         check_mem();
 
+        {
+            my $doc = XML::LibXML->createDocument;
+            for (1..$times_through)        {
+                make_doc2( $doc );
+            }
+        }
+        ok(1);
+        check_mem();
+
         print("# DTD string parsing\n");
 
         my $dtdstr;
 
         }
 
+#        {
+#            print "# ENCODING TESTS \n";
+#            my $string = "test � � is a test string to test iso encoding";
+#            my $encstr = encodeToUTF8( "iso-8859-1" , $string );
+#            for ( 1..$times_through ) {
+#                my $str = encodeToUTF8( "iso-8859-1" , $string );
+#            }
+#            ok(1);
+#            check_mem();
+
+#            for ( 1..$times_through ) {
+#                my $str = encodeToUTF8( "iso-8859-2" , "abc" );
+#            }
+#            ok(1);
+#            check_mem();
+#    
+#            for ( 1..$times_through ) {
+#                my $str = decodeFromUTF8( "iso-8859-1" , $encstr );
+#            }
+#            ok(1);
+#            check_mem();
+#        }
         {
-            print "# ENCODING TESTS \n";
-            my $string = "test � � is a test string to test iso encoding";
-            my $encstr = encodeToUTF8( "iso-8859-1" , $string );
-            for ( 1..$times_through ) {
-                my $str = encodeToUTF8( "iso-8859-1" , $string );
+            print "# NAMESPACE TESTS \n";
+
+            my $string = '<foo:bar xmlns:foo="bar"><foo:a/><foo:b/></foo:bar>';
+
+            my $doc = XML::LibXML->new()->parse_string( $string );
+
+            for (1..$times_through) {
+                my @ns = $doc->documentElement()->getNamespaces();
+                # warn "ns : " . $_->localname . "=>" . $_->href foreach @ns;
+                my $prefix = $_->localname foreach @ns;
+                my $name = $doc->documentElement->nodeName;
+            }  
+            check_mem();
+            ok(1);
+        }   
+
+        {
+            print "# SAX PARSER\n";
+
+        my %xmlStrings = (
+            "SIMPLE"      => "<xml1><xml2><xml3></xml3></xml2></xml1>",
+            "SIMPLE TEXT" => "<xml1> <xml2>some text some text some text </xml2> </xml1>",
+            "SIMPLE COMMENT" => "<xml1> <xml2> <!-- some text --> <!-- some text --> <!--some text--> </xml2> </xml1>",
+            "SIMPLE CDATA" => "<xml1> <xml2><![CDATA[some text some text some text]]></xml2> </xml1>",
+            "SIMPLE ATTRIBUTE" => '<xml1  attr0="value0"> <xml2 attr1="value1"></xml2> </xml1>',
+            "NAMESPACES SIMPLE" => '<xml:xml1 xmlns:xml="foo"><xml:xml2/></xml:xml1>',
+            "NAMESPACES ATTRIBUTE" => '<xml:xml1 xmlns:xml="foo"><xml:xml2 xml:foo="bar"/></xml:xml1>',
+        );
+
+            my $handler = sax_null->new;
+            my $parser  = XML::LibXML->new;
+            $parser->set_handler( $handler );
+
+            check_mem();
+       
+            foreach my $key ( keys %xmlStrings )  {
+                print "# $key \n";
+                for (1..$times_through) {
+                    my $doc = $parser->parse_string( $xmlStrings{$key} );
+                }
+
+                check_mem();
             }
             ok(1);
+        }
+
+        {
+            print "# PUSH PARSER\n";
+
+        my %xmlStrings = (
+            "SIMPLE"      => ["<xml1>","<xml2><xml3></xml3></xml2>","</xml1>"],
+            "SIMPLE TEXT" => ["<xml1> ","<xml2>some text some text some text"," </xml2> </xml1>"],
+            "SIMPLE COMMENT" => ["<xml1","> <xml2> <!","-- some text --> <!-- some text --> <!--some text-","-> </xml2> </xml1>"],
+            "SIMPLE CDATA" => ["<xml1> ","<xml2><!","[CDATA[some text some text some text]","]></xml2> </xml1>"],
+            "SIMPLE ATTRIBUTE" => ['<xml1 ','attr0="value0"> <xml2 attr1="value1"></xml2>',' </xml1>'],
+            "NAMESPACES SIMPLE" => ['<xml:xml1 xmlns:x','ml="foo"><xml:xml2','/></xml:xml1>'],
+            "NAMESPACES ATTRIBUTE" => ['<xml:xml1 xmlns:xml="foo">','<xml:xml2 xml:foo="bar"/></xml',':xml1>'],
+        );
+
+            my $handler = sax_null->new;
+            my $parser  = XML::LibXML->new;
+
             check_mem();
+       
+            foreach my $key ( keys %xmlStrings )  {
+                print "# $key \n";
+                for (1..$times_through) {
+                    map { $parser->push( $_ ) } @{$xmlStrings{$key}};
+                    my $doc = $parser->finish_push();
+                }
 
-            for ( 1..$times_through ) {
-                my $str = encodeToUTF8( "iso-8859-2" , "abc" );
+                check_mem();
             }
             ok(1);
+        }
+
+        {
+            print "# SAX PUSH PARSER\n";
+
+        my %xmlStrings = (
+            "SIMPLE"      => ["<xml1>","<xml2><xml3></xml3></xml2>","</xml1>"],
+            "SIMPLE TEXT" => ["<xml1> ","<xml2>some text some text some text"," </xml2> </xml1>"],
+            "SIMPLE COMMENT" => ["<xml1","> <xml2> <!","-- some text --> <!-- some text --> <!--some text-","-> </xml2> </xml1>"],
+            "SIMPLE CDATA" => ["<xml1> ","<xml2><!","[CDATA[some text some text some text]","]></xml2> </xml1>"],
+            "SIMPLE ATTRIBUTE" => ['<xml1 ','attr0="value0"> <xml2 attr1="value1"></xml2>',' </xml1>'],
+            "NAMESPACES SIMPLE" => ['<xml:xml1 xmlns:x','ml="foo"><xml:xml2','/></xml:xml1>'],
+            "NAMESPACES ATTRIBUTE" => ['<xml:xml1 xmlns:xml="foo">','<xml:xml2 xml:foo="bar"/></xml',':xml1>'],
+        );
+
+            my $handler = sax_null->new;
+            my $parser  = XML::LibXML->new;
+            $parser->set_handler( $handler );
+
             check_mem();
-    
-            for ( 1..$times_through ) {
-                my $str = decodeFromUTF8( "iso-8859-1" , $encstr );
+       
+            foreach my $key ( keys %xmlStrings )  {
+                print "# $key \n";
+                for (1..$times_through) {
+                    map { $parser->push( $_ ) } @{$xmlStrings{$key}};
+                    my $doc = $parser->finish_push();
+                }
+
+                check_mem();
             }
             ok(1);
-            check_mem();
         }
+
     }
 }
 
     return $document
 }
 
+sub make_doc2 {
+    my $docA = shift;
+    my $docB = XML::LibXML::Document->new;
+    my $e1   = $docB->createElement( "A" );
+    my $e2   = $docB->createElement( "B" );
+    $e1->appendChild( $e2 );
+    $docA->setDocumentElement( $e1 );
+}
+
 sub check_mem {
     my $initialise = shift;
     # Log Memory Usage
     $doc->setDocumentElement( $node1 );
 }
 
+package sax_null;
+
+require Devel::Peek;
+use Data::Dumper;
+
+sub new {
+    my $class = shift;
+    bless {}, $class;
+}
+
+sub start_document {
+    my $self = shift;
+    my $dummy = shift;
+}
+
+sub xml_decl {
+    my $self = shift;
+    my $dummy = shift;
+}
+
+sub start_element {
+    my $self = shift;
+    my $dummy = shift;
+    # warn Dumper( $dummy );
+}
+
+sub end_element {
+    my $self = shift;
+    my $dummy = shift;
+}
+
+sub start_cdata {
+    my $self = shift;
+    my $dummy = shift;
+}
+
+sub end_cdata {
+    my $self = shift;
+    my $dummy = shift;
+}
+
+sub start_prefix_mapping {
+    my $self = shift;
+    my $dummy = shift;
+}
+
+sub end_prefix_mapping {
+    my $self = shift;
+    my $dummy = shift;
+}
+
+sub characters {
+    my $self = shift;
+    my $dummy = shift;
+}
+
+sub comment {
+    my $self = shift;
+    my $dummy = shift;
+}
+
+
+sub end_document {
+    my $self = shift;
+    my $dummy = shift;
+}
+
+sub error {
+    my $self = shift;
+    my $msg  = shift;
+    die( $msg );
+}
+
+1;