Commits

Anonymous committed 645653c

this commit is basicly a sync of my local checkout with the repository.
i simply forgot which fixes i did until this version, but several issues
that are reported on the perlxml list were already fixed.

Modified Files:
Changes MANIFEST
+ package information

LibXML.xs dom.c perl-libxml-mm.c
lib/XML/LibXML/Boolean.pm lib/XML/LibXML/SAX.pm
lib/XML/LibXML/SAX/Builder.pm
+ more fixes less

t/02parse.t t/08findnodes.t t/09xpath.t t/10ns.t
+ more tests to find bugs faster

  • Participants
  • Parent commits 821604c

Comments (0)

Files changed (12)

 versions of the package. 
 
 1.54
+   - fixed problem with empty document fragments
    - bad tag and attribute names cannot be created anymore
    - Catalog interface is aware about libxml2 configuration
    - XML::LibXML should work now on systems without having zlib installed
     else {
        croak("%s",SvPV(sv, PL_na));
     }
+
     SvREFCNT_dec(sv);
 }
 
     /* we fetch all switches and callbacks from the hash */
     SV** item    = NULL;
     SV*  item2   = NULL;
+    
+    xmlGetWarningsDefaultValue = 0;
 
     if ( self != NULL ) {
         /* first fetch the values from the hash */
     xmlKeepBlanksDefaultValue = 1;
     xmlLoadExtDtdDefaultValue = 5;
     xmlPedanticParserDefaultValue = 0;
+    xmlSetGenericErrorFunc(NULL, NULL);
 #ifdef LIBXML_CATALOG_ENABLED
     /* xmlCatalogSetDebug(10); */
     xmlInitializeCatalog(); /* use catalog data */
             LibXML_cleanup_parser();    
 
             sv_2mortal(LibXML_error);
-            LibXML_croak_error();
+            if ( (int) rv == -1 ) {
+                LibXML_croak_error();
+            }
 
             if ( rv != NULL ) {
                 /* now we append the nodelist to a document
             xs_warn( "empty string" );
             XSRETURN_UNDEF;
         }
-/*        LibXML_init_error(); */
+        LibXML_init_error(); 
         LibXML_init_parser(self);
         xmlParseChunk(ctxt, (const char *)chunk, len, 0);
         LibXML_cleanup_callbacks();
         LibXML_cleanup_parser();
     
         sv_2mortal(LibXML_error); 
-        LibXML_croak_error();
+        if ( ctxt->wellFormed == 0 ) {
+            LibXML_croak_error();
+        }
 
         RETVAL = 1;
     OUTPUT:
         }
     CODE:
         PmmNODE( SvPROXYNODE( pctxt ) ) = NULL;
+        LibXML_init_error(); 
         LibXML_init_parser(self); 
 
         xmlParseChunk(ctxt, "", 0, 1); /* finish the parse */
         if ( self->doc != nNode->doc ) {
             domImportNode( self->doc, nNode, 1 );
         }
-        ret = xmlReplaceNode( self, nNode );
+
+        if ( self->type != XML_ATTRIBUTE_NODE ) {
+              ret = domReplaceChild( self->parent, nNode, self);
+        }
+        else {
+             ret = xmlReplaceNode( self, nNode );
+        }
         if ( ret ) {
             if ( ret->type == XML_ATTRIBUTE_NODE ) {
                 docfrag = NULL;
         int oldTagFlag = xmlSaveNoEmptyTags;
     CODE:
         internalFlag = perl_get_sv("XML::LibXML::setTagCompression", 0);
-
+    
         if ( internalFlag ) {
             xmlSaveNoEmptyTags = SvTRUE(internalFlag);
         }
                          self, 0, format);
             xmlIndentTreeOutput = t_indent_var;
         }
+
         if ( buffer->content != 0 ) {
             ret= xmlStrdup( buffer->content );
         }
 t/18docfree.t
 t/19encoding.t
 t/20extras.t
-t/22iterator.t
 t/23rawfunctions.t
 lib/XML/LibXML/Attr.pod
 lib/XML/LibXML/Comment.pod
 lib/XML/LibXML/DocumentFragment.pod
 lib/XML/LibXML/Namespace.pod
 lib/XML/LibXML/NodeList.pm
-lib/XML/LibXML/Iterator.pm
 lib/XML/LibXML/Literal.pm
 lib/XML/LibXML/Boolean.pm
 lib/XML/LibXML/Number.pm
 #include <libxml/xmlIO.h>
 #include <libxml/xpath.h>
 #include <libxml/xpathInternals.h>
-
+#include <libxml/globals.h>
 #include <stdio.h>
 
 #define warn(string) fprintf(stderr, string) 
         domRemoveChild( self, old );
         domAppendChild( self, new );
     }
+    else if ( new->type == XML_DOCUMENT_FRAG_NODE 
+              && new->children == NULL ) {
+        /* want to replace with an empty fragment, then remove ... */
+        domRemoveChild( self, old );
+    }
     else {
         domAddNodeToList(new, old->prev, old->next );
         old->parent = old->next = old->prev = NULL;    

File lib/XML/LibXML/Boolean.pm

 # $Id$
+# Copyright 2001-2002, AxKit.com Ltd. All rights reserved.
 
 package XML::LibXML::Boolean;
 use XML::LibXML::Number;

File lib/XML/LibXML/SAX.pm

 # $Id$
-
+# Copyright (c) 2001-2002, AxKit.com Ltd. All rights reserved.
 package XML::LibXML::SAX;
 
 use strict;

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

     return bless {@_}, $class;
 }
 
+sub result { $_[0]->{LAST_DOM}; }
+
 sub done {
     my ($self) = @_;
     my $dom = $self->{DOM};
     $dom = $self->{Parent} unless defined $dom; # this is for parsing document chunks
+
     delete $self->{NamespaceStack};
     delete $self->{Parent};
     delete $self->{DOM};
 
+    $self->{LAST_DOM} = $dom;
+
     return $dom;
 }
 

File perl-libxml-mm.c

         xs_warn("   perlnode found\n" );
         if ( sv_derived_from(perlnode, "XML::LibXML::Node")  ) {
             proxy = SvPROXYNODE(perlnode);
-            xs_warn( "is a xmlNodePtr structure\n" );
-            retval = PmmNODE( proxy ) ;
+            if ( proxy != NULL ) {
+                xs_warn( "is a xmlNodePtr structure\n" );
+                retval = PmmNODE( proxy ) ;
+            }
 
             if ( retval != NULL
                  && ((ProxyNodePtr)retval->_private) != proxy ) {
 use Test;
 use IO::File;
 
-BEGIN { plan tests => 460 };
+BEGIN { plan tests => 469 };
 use XML::LibXML;
 use XML::LibXML::Common qw(:libxml);
 use XML::LibXML::SAX;
 XML_DECL. '<foobar foo="bar"/>',
 XML_DECL. '<foobar foo="\'bar>"/>',
 XML_DECL. '<bar:foobar foo="bar"><bar:foo/></bar:foobar>',
+'<bar:foobar/>'
                     );
 
 my @goodWFNSStrings = (
 print "# 2 PUSH PARSER\n";
 
 {
+    my $pparser = XML::LibXML->new();
     print "# 2.1 PARSING WELLFORMED DOCUMENTS\n";
-    foreach my $key ( keys %goodPushWF ) {
+    foreach my $key ( qw(single1 single2 single3 single4 single5 single6 
+                         single7 single8 single9 multiple1 multiple2 multiple3
+                         multiple4 multiple5 multiple6 multiple7 multiple8 
+                         multiple9 multiple10 comment1 comment2 comment3
+                         comment4 comment5 attr1 attr2 attr3 prefix1 prefix2 
+                         prefix3 ns1 ns2 ns3 ns4 ns5 ns6 dtd1 dtd2) ) {
+        print "# key is $key\n";
         foreach ( @{$goodPushWF{$key}} ) {
-            $parser->parse_chunk( $_ );
+            $pparser->parse_chunk( $_ );
         }
 
         my $doc;
-        eval {$doc = $parser->parse_chunk("",1); };
+        eval {$doc = $pparser->parse_chunk("",1); };
+        print "# caught an error $@ \n" if $@; 
+        print "# document seems to be ok \n" if $doc;
         ok($doc && !$@);      
     }
 
         ok( $doc );
 
         # skip the nested node tests until there is a xmlNormalizeNs().
-        ok(1),next if $i > 2;
+        #ok(1),next if $i > 2;
 
         ok( $doc->toString(), $str );
         $i++
     # libxml2 will only do some fixing. this will lead to multiple 
     # declarations, if a node with a new namespace is added.
 
-    # my $vstring = q{<foo xmlns:bar="http://foo.bar">bar<bar:bi/></foo>};
-    my $vstring = qr(<foo xmlns:bar="http://foo.bar">bar<bar:bi( xmlns:bar="http://foo.bar")?/></foo>);
+    my $vstring = q{<foo xmlns:bar="http://foo.bar">bar<bar:bi/></foo>};
+    # my $vstring = q{<foo xmlns:bar="http://foo.bar">bar<bar:bi xmlns:bar="http://foo.bar"/></foo>};
     ok($root->toString, $vstring );
 
     print "# 3.3 INTERNAL SUBSETS\n";
 
 print "# 5 PARSE WELL BALANCED CHUNKS\n";
 {
-    my $MAX_WF_C = 10;
+    my $MAX_WF_C = 11;
     my $MAX_WB_C = 16;
 
     my %chunks = ( 
                     wellformed7  => '<A><K/></A>',
                     wellformed8  => '<A xmlns="E"/>',
                     wellformed9  => '<F:A xmlns:F="G" F:A="B">D</F:A>',
-                    wellformed10 => '<!--D-->',                    
+                    wellformed10 => '<!--D-->',      
+                    wellformed11  => '<A xmlns:F="E"/>',              
                     wellbalance1 => '<A/><A/>',
                     wellbalance2 => '<A></A><A></A>',
                     wellbalance3 => '<A B="C"/><A B="H"/>',
     );
 
 
-    my $parser = XML::LibXML->new;
+    my $pparser = XML::LibXML->new;
     
     print "# 5.1 DOM CHUNK PARSER\n";
 
     for ( 1..$MAX_WF_C ) {
-        my $frag = $parser->parse_xml_chunk($chunks{'wellformed'.$_});
+        my $frag = $pparser->parse_xml_chunk($chunks{'wellformed'.$_});
         ok($frag);
         if ( $frag->nodeType == XML_DOCUMENT_FRAG_NODE
              && $frag->hasChildNodes ) {
             if ( $frag->firstChild->isSameNode( $frag->lastChild ) ) {
+                print "# well formness test $_\n";
                 if ( $chunks{'wellformed'.$_} =~ /\<A\>\<\/A\>/ ) {
-                    $_--;
+                    $_--; # because we cannot distinguish between <a/> and <a></a>
                 }
+  
                 ok($frag->toString,$chunks{'wellformed'.$_});                
                 next;
             }
     }
 
     for ( 1..$MAX_WB_C ) {
-        my $frag = $parser->parse_xml_chunk($chunks{'wellbalance'.$_});
+        my $frag = $pparser->parse_xml_chunk($chunks{'wellbalance'.$_});
         ok($frag);
         if ( $frag->nodeType == XML_DOCUMENT_FRAG_NODE
              && $frag->hasChildNodes ) {
         ok(0);
     }
 
-    eval { my $fail = $parser->parse_xml_chunk(undef); };
+    eval { my $fail = $pparser->parse_xml_chunk(undef); };
     ok($@);
 
-    eval { my $fail = $parser->parse_xml_chunk(""); };
+    eval { my $fail = $pparser->parse_xml_chunk(""); };
     ok($@);
 
     foreach my $str ( @badWBStrings ) {
-        eval { my $fail = $parser->parse_xml_chunk($str); };  
+        eval { my $fail = $pparser->parse_xml_chunk($str); };  
         ok($@);
     }
 
     print "# 5.2 SAX CHUNK PARSER\n";
 
     my $handler = XML::LibXML::SAX::Builder->new();
+    my $parser = XML::LibXML->new;
     $parser->set_handler( $handler );
     for ( 1..$MAX_WF_C ) {
         my $frag = $parser->parse_xml_chunk($chunks{'wellformed'.$_});

File t/08findnodes.t

 use Test;
-BEGIN { plan tests=>35}
+BEGIN { plan tests => 44 };
 END {ok(0) unless $loaded;}
 use XML::LibXML;
 $loaded = 1;
     ok($@);
 }
 
+
+{
+    # as reported by jian lou:
+    # 1. getElementByTagName("myTag") is not working is
+    # "myTag" is a node directly under root. Same problem
+    # for findNodes("//myTag")
+    # 2. When I add new nodes into DOM tree by
+    # appendChild(). Then try to find them by
+    # getElementByTagName("newNodeTag"), the newly created
+    # nodes are not returned. ...
+    #
+    # this seems not to be a problem by XML::LibXML itself, but newer versions
+    # of libxml2 (newer is 2.4.27 or later)
+    #
+    my $doc = XML::LibXML->createDocument();
+    my $root= $doc->createElement( "A" );
+    $doc->setDocumentElement($root);
+
+    my $b= $doc->createElement( "B" );
+    $root->appendChild( $b );
+
+    my @list = $doc->findnodes( '//A' );
+    ok( scalar @list );
+    ok( $list[0]->isSameNode( $root ) );
+
+    @list = $doc->findnodes( '//B' );
+    ok( scalar @list );
+    ok( $list[0]->isSameNode( $b ) );
+
+
+    # @list = $doc->getElementsByTagName( "A" );
+    # ok( scalar @list );
+    # ok( $list[0]->isSameNode( $root ) );        
+
+    @list = $root->getElementsByTagName( 'B' );
+    ok( scalar @list );
+    ok( $list[0]->isSameNode( $b ) );
+}
+
+{
+    print "# test potential unbinding-segfault-problem \n";
+    my $doc = XML::LibXML->createDocument();
+    my $root= $doc->createElement( "A" );
+    $doc->setDocumentElement($root);
+
+    my $b= $doc->createElement( "B" );
+    $root->appendChild( $b );
+    my $c= $doc->createElement( "C" );
+    $b->appendChild( $c );
+    $b= $doc->createElement( "B" );
+    $root->appendChild( $b );
+    $c= $doc->createElement( "C" );
+    $b->appendChild( $c );
+    
+    my @list = $root->findnodes( "B" );
+    ok( scalar(@list) , 2 );
+    foreach my $node ( @list ) {
+        my @subnodes = $node->findnodes( "C" );
+        $node->unbindNode() if ( scalar( @subnodes ) );
+        ok(1);
+    }
+}
+
+# --------------------------------------------------------------------------- #
 sub finddoc {
     my $doc = shift;
     return unless defined $doc;
 use Test;
 use strict;
 
-BEGIN { plan tests => 20 };
+BEGIN { plan tests => 22 };
 use XML::LibXML;
 
 my $xmlstring = <<EOSTR;
     ok( $result == 0 );
 }
 
+{
+    # test the strange segfault after xpathing
+    my $root = $doc->documentElement();
+    foreach my $bar ( $root->findnodes( 'bar' )  ) {
+        $root->removeChild($bar);
+    }
+    ok(1);
+    # warn $root->toString();
+    
 
+    $doc =  $parser->parse_string( $xmlstring );
+    my @bars = $doc->findnodes( '//bar' );
+    
+    foreach my $node ( @bars ) {
+        $node->parentNode()->removeChild( $node );
+    }
+    ok(1);
+}
 use Test;
-BEGIN { plan tests=>21; }
+BEGIN { plan tests=>22; }
 use XML::LibXML;
 use XML::LibXML::Common qw(:libxml);
 
     my @attrb = $d->attributes;
     ok( scalar(@attrb), 1 );
     ok( $attrb[0]->nodeType, 18 );
+}
+
+print "# 6. lossless stetting of namespaces with setAttribute\n";
+# reported by Kurt George Gjerde
+
+{
+    my $doc = XML::LibXML->createDocument; 
+    my $root = $doc->createElementNS('http://example.com', 'document');
+    $root->setAttribute('xmlns:xxx', 'http://example.com');
+    $root->setAttribute('xmlns:yyy', 'http://yonder.com');
+    $doc->setDocumentElement( $root );
+
+    my $strnode = $root->toString();
+    ok ( $strnode =~ /xmlns:xxx/ and $strnode =~ /xmlns=/ );
 }