Commits

pa...@9ae0c189-cd1f-4510-a509-f4891f5cf20d  committed e7a6f92

- include Schema/RelaxNG code only with libxml2 >= 2.6.0 (to support old libxml2)
- applied patch to example/cb_example.pl (bug 4262)
- fixed insertBefore/insertAfter on empty elements (bug 3691)
- more DOM conformant XML::LibXML->createDocument API (by Robin Berjon)
- fixed encoding problems with API calls in document encoding
- improved support for importing DTD subsets
- fixed DTD validation error reporting problems with libxml2-2.6.x
- fixed compilation problems with libxml2-2.6.x

  • Participants
  • Parent commits acafc11

Comments (0)

Files changed (10)

 Revision history for Perl extension XML::LibXML
 
 1.57
+   - include Schema/RelaxNG code only with libxml2 >= 2.6.0 (to support old libxml2)
+   - applied patch to example/cb_example.pl (bug 4262)
+   - fixed insertBefore/insertAfter on empty elements (bug 3691)
+   - more DOM conformant XML::LibXML->createDocument API (by Robin Berjon)
+   - fixed encoding problems with API calls in document encoding
+   - improved support for importing DTD subsets
+   - fixed DTD validation error reporting problems with libxml2-2.6.x
+   - fixed compilation problems with libxml2-2.6.x
+   - fixed XML::LibXML::Number to support negative numbers
    - added XML Schema validation interface (XML::LibXML::Schema)
    - added XML RelaxNG validation interface (XML::LibXML::RelaxNG)
 
 }
 
 #-------------------------------------------------------------------------#
+# DOM Level 2 document constructor                                        #
+#-------------------------------------------------------------------------#
+
+sub createDocument {
+   my $self = shift;
+   if (!@_ or $_[0] =~ m/^\d\.\d$/) {
+     # for backward compatibility
+     return XML::LibXML::Document->new(@_);
+   }
+   else {
+     # DOM API: createDocument(namespaceURI, qualifiedName, doctype?)
+     my $doc = XML::LibXML::Document-> new;
+     my $el = $doc->createElementNS(shift, shift);
+     $doc->setDocumentElement($el);
+     $doc->setExternalSubset(shift) if @_;
+     return $doc;
+   }
+}
+
+#-------------------------------------------------------------------------#
 # callback functions                                                      #
 #-------------------------------------------------------------------------#
 sub match_callback {
 #define DEBUG_C14N
 
 /* libxml2 stuff */
+#include <libxml/xmlversion.h>
+#include <libxml/globals.h>
 #include <libxml/xmlmemory.h>
 #include <libxml/parser.h>
 #include <libxml/parserInternals.h>
 #include <libxml/xmlerror.h>
 #include <libxml/xinclude.h>
 #include <libxml/valid.h>
+
+#if LIBXML_VERSION >= 20600
+#define HAVE_SCHEMAS
 #include <libxml/relaxng.h>
 #include <libxml/xmlschemas.h>
+#endif
 
 #ifdef LIBXML_CATALOG_ENABLED
 #include <libxml/catalog.h>
 }
 #endif
 
+/*
 #ifdef VMS
 extern int xmlDoValidityCheckingDefaultVal;
 #define xmlDoValidityCheckingDefaultValue xmlDoValidityCheckingDefaultVal
 LIBXML_DLL_IMPORT extern int xmlKeepBlanksDefaultValue;
 LIBXML_DLL_IMPORT extern int xmlLoadExtDtdDefaultValue;
 LIBXML_DLL_IMPORT extern int xmlPedanticParserDefaultValue;
+*/
 
 #define TEST_PERL_FLAG(flag) \
     SvTRUE(perl_get_sv(flag, FALSE)) ? 1 : 0
        STRLEN n_a;
        croak("read on filehandle failed: %s", SvPV(ERRSV, n_a));
        POPs ;
-    }				  
+    }                             
 
     read_results = POPs;
 
         
         if (SvTRUE(ERRSV)) {
             STRLEN n_a;
-       	    croak("input match callback died: %s", SvPV(ERRSV, n_a));
-       	    POPs ;
-    	}				  
+            croak("input match callback died: %s", SvPV(ERRSV, n_a));
+            POPs ;
+        }                                 
 
         res = POPs;
 
 
         if (SvTRUE(ERRSV)) {
             STRLEN n_a;
-       	    croak("input callback died: %s", SvPV(ERRSV, n_a));
-       	    POPs ;
+            croak("input callback died: %s", SvPV(ERRSV, n_a));
+            POPs ;
         } 
 
         results = POPs;
 
         if (SvTRUE(ERRSV)) {
             STRLEN n_a;
-       	    croak("read callback died: %s", SvPV(ERRSV, n_a));
-       	    POPs ;
+            croak("read callback died: %s", SvPV(ERRSV, n_a));
+            POPs ;
         }
 
         output = POPp;
 
         if (SvTRUE(ERRSV)) {
             STRLEN n_a;
-       	    croak("close callback died: %s", SvPV(ERRSV, n_a));
-       	    POPs ;
+            croak("close callback died: %s", SvPV(ERRSV, n_a));
+            POPs ;
         }
 
         PUTBACK;
 
         if (SvTRUE(ERRSV)) {
             STRLEN n_a;
-       	    croak("write method call died: %s", SvPV(ERRSV, n_a));
-       	    POPs ;
+            croak("write method call died: %s", SvPV(ERRSV, n_a));
+            POPs ;
         }
 
         FREETMPS;
         
         if (SvTRUE(ERRSV)) {
             STRLEN n_a;
-       	    croak("external entity callback died: %s", SvPV(ERRSV, n_a));
-       	    POPs ;
+            croak("external entity callback died: %s", SvPV(ERRSV, n_a));
+            POPs ;
         }
 
         results = POPs;
         }
 
         ctxt->_private = (void*)self;
+
+        /* make libxml2-2.6 display line number on error */
+        if ( ctxt->input != NULL ) {
+          ctxt->input->filename = xmlStrdup((const xmlChar *) "");
+        }
         
         xs_warn( "context initialized \n");        
 
 /*        sv_2mortal( LibXML_error );
         LibXML_croak_error();
 */
-    	if (result == NULL) {
-	        xs_warn("Failed to convert doc to string");           
+        if (result == NULL) {
+                xs_warn("Failed to convert doc to string");           
             XSRETURN_UNDEF;
-    	} else {
+        } else {
             /* warn("%s, %d\n",result, len); */
             RETVAL = C2Sv( result, self->encoding );
             xmlFree(result);
         sv_2mortal( LibXML_error );
         LibXML_croak_error();
 
-    	if (result == NULL) {
+        if (result == NULL) {
             XSRETURN_UNDEF;
-      	} else {
+        } else {
             /* warn("%s, %d\n",result, len); */
             RETVAL = newSVpvn((char *)result, (STRLEN)len);
             xmlFree(result);
         }
     CODE:
         if ( dtd && dtd != self->extSubset ) {
-            if ( dtd->doc != self ) {
-                croak( "can't import DTDs" );
-                domImportNode( self, (xmlNodePtr) dtd,1);
+            if ( dtd->doc == NULL ) {
+                xmlSetTreeDoc( (xmlNodePtr) dtd, self );
+            } else if ( dtd->doc != self ) {
+                domImportNode( self, (xmlNodePtr) dtd,1); 
             }
     
             if ( dtd == self->intSubset ) {
         }
     CODE:
         if ( dtd && dtd != self->intSubset ) {
-            if ( dtd->doc != self ) {
-                croak( "can't import DTDs" );
-                domImportNode( self, (xmlNodePtr) dtd,1);
-            }
-    
+            if ( dtd->doc == NULL ) {
+               xmlSetTreeDoc( (xmlNodePtr) dtd, self );
+            } else if ( dtd->doc != self ) {
+               domImportNode( self, (xmlNodePtr) dtd,1); 
+            }    
+
             if ( dtd == self->extSubset ) {
                 self->extSubset = NULL;
             }
             xs_warn("childnodes start");
             while ( cld ) {
                 if( wantarray != G_SCALAR ) {
-	                element = PmmNodeToSv(cld, PmmOWNERPO(PmmPROXYNODE(self)) );
+                        element = PmmNodeToSv(cld, PmmOWNERPO(PmmPROXYNODE(self)) );
                     XPUSHs(sv_2mortal(element));
                 }
                 cld = cld->next;
         }
         else {
             xmlBufferFree( buffer );
-	        xs_warn("Failed to convert doc to string");           
+                xs_warn("Failed to convert doc to string");           
             XSRETURN_UNDEF;
         }
     OUTPUT:
             newNode->prev = prev;
             self->last = newNode;
         }
-     	RETVAL = PmmNodeToSv(newNode, PmmOWNERPO(PmmPROXYNODE(self)) );
+        RETVAL = PmmNodeToSv(newNode, PmmOWNERPO(PmmPROXYNODE(self)) );
     OUTPUT:
         RETVAL
 
     OUTPUT:
         RETVAL
 
-
+#ifdef HAVE_SCHEMAS
 
 MODULE = XML::LibXML         PACKAGE = XML::LibXML::RelaxNG
 
     OUTPUT:
         RETVAL
 
+#endif /* HAVE_SCHEMAS */
    o past 2.5.0: tested; working
    o version 2.5.5: tested; tests pass, but known as broken
    o up to version 2.5.10: tested; working
+   o 2.6.0: tested; not working
+   o 2.6.1: tested; working
 
 It happens, that an older version of libxml2 passes all tests under certain
 conditions. This is no reason to assume that version to work on all platforms.
 
 * xmlReader Interface.
 * RelaxNG, libxml2 Regex interface.
+* structured Error support (Petr Pajas)
     if ( self == NULL || newChild == NULL ) {
         return NULL;
     }
-   
+
     if ( refChild != NULL ) {
         if ( refChild->parent != self
              || (  newChild->type     == XML_DOCUMENT_FRAG_NODE 
         }
     }
 
+    if ( self->children == NULL ) {
+        return domAppendChild( self, newChild );
+    }
+   
     if ( !(domTestHierarchy( self, newChild )
            && domTestDocument( self, newChild ))) {
         xmlGenericError(xmlGenericErrorContext,"HIERARCHIY_REQUEST_ERR\n");

File example/cb_example.pl

 use XML::LibXML;
+use IO::File;
 
 # first instanciate the parser
 my $parser = XML::LibXML->new();
 
     my $handler = new IO::File;
     if ( not $handler->open( "<$uri" ) ){
-        $file = 0;
-    }   
-   
-    return $file;
+        $handler = 0;
+    }
+    
+    return $handler;
 }
 
 sub read_uri {
     my $length  = shift;
     my $buffer = undef;
     if ( $handler ) {
-        $handler->read( $rv , $length );
+        $handler->read( $buffer, $length );
     }
     return $buffer;
 }

File perl-libxml-mm.c

     xmlChar *retval = NULL;
     xmlBufferPtr in = NULL, out = NULL;
 
-    if ( charset == 1 ) {
+    if ( charset == XML_CHAR_ENCODING_UTF8 ) {
         /* warn("use UTF8 for encoding ... %s ", string); */
-        return xmlStrdup( string );
-    }
-
-    if ( charset > 1 ) {
-        /* warn( "use document encoding %s (%d)", encoding, charset ); */
-        coder= xmlGetCharEncodingHandler( charset );
-    }
+	return xmlStrdup( string );
+    } 
     else if ( charset == XML_CHAR_ENCODING_ERROR ){
         /* warn("no standard encoding %s\n", encoding); */
         coder =xmlFindCharEncodingHandler( (const char *)encoding );
     }
-    else {
+    else if ( charset == XML_CHAR_ENCODING_NONE ){
         xs_warn("no encoding found \n");
+    } else {
+        /* warn( "use document encoding %s (%d)", encoding, charset ); */
+        coder= xmlGetCharEncodingHandler( charset );
     }
 
     if ( coder != NULL ) {
     xmlChar *retval = NULL;
     xmlBufferPtr in = NULL, out = NULL;
 
-    if ( charset == 1 ) {
-
-        return xmlStrdup( string );
+    if ( charset == XML_CHAR_ENCODING_UTF8 ) {
+	return xmlStrdup( string );
+    } 
+    else if ( charset == XML_CHAR_ENCODING_ERROR ){
+        coder =xmlFindCharEncodingHandler( (const char *)encoding );
     }
-
-    if ( charset > 1 ) {
+    else if ( charset == XML_CHAR_ENCODING_NONE ){
+        xs_warn("no encoding found \n");
+    } else {
         coder= xmlGetCharEncodingHandler( charset );
     }
-    else if ( charset == XML_CHAR_ENCODING_ERROR ){
-        coder = xmlFindCharEncodingHandler( (const char *) encoding );
-    }
-    else {
-        xs_warn("no encoding found\n");
-    }
 
     if ( coder != NULL ) {
         /* warn( "do encoding %s", string ); */
         xmlDocPtr real_doc = refnode->doc;
         if ( real_doc != NULL && real_doc->encoding != NULL ) {
 
-            xmlChar * decoded = PmmFastDecodeString( PmmDocEncoding(real_doc) ,
-                                                     (const xmlChar *)string,
-                                                     (const xmlChar*)real_doc->encoding);
+            xmlChar * decoded = PmmDecodeString( (const xmlChar*)real_doc->encoding,
+						 (const xmlChar *)string );
             len = xmlStrlen( decoded );
 
-            if ( real_doc->charset == XML_CHAR_ENCODING_UTF8 ) {
+            if ( PmmDocEncoding(real_doc) == XML_CHAR_ENCODING_UTF8 
+		 /* most probably true, since libxml2 always 
+                  * sets doc->charset to UTF8, see tree.c:
+                  *
+		  * The in memory encoding is always UTF8
+		  * This field will never change and would
+		  * be obsolete if not for binary compatibility.
+		  */
+
+		 && (real_doc->encoding == NULL ||
+		     xmlParseCharEncoding(real_doc->encoding)==XML_CHAR_ENCODING_UTF8 )) {
                 /* create an UTF8 string. */       
                 xs_warn("set UTF8 string");
                 /* create the SV */
                         xs_warn( "domEncodeString!" );
                       /*  if ( string == NULL || *string == 0 ) warn("string is empty" ); */
                        
-                        ts= PmmFastEncodeString( PmmDocEncoding(real_dom),
-                                                 string,
-                                                 (const xmlChar*)real_dom->encoding );
+                        ts= PmmEncodeString( (const xmlChar*)real_dom->encoding,
+					     string );
 
                         xs_warn( "done!" );
                         if ( string != NULL ) {
     $parser->validation(1);
 
     eval { $parser->parse_string( $badxml ); };
-    ok( $@ =~ /^:0:/ );
+    # correct line number may or may not be present
+    # depending on libxml2 version
+    ok( $@ =~ /^:[03]:/ );
 
     $parser->line_numbers(1);
     eval { $parser->parse_string( $badxml ); };

File t/19encoding.t

 #
 use Test;
 
-BEGIN { 
-    my $tests        = 0;
+BEGIN {
+    my $tests        = 1;
     my $basics       = 0;
-    my $magic        = 7;    
+    my $magic        = 6;
 
-    if ( $] >= 5.008 ) { 
-        print "# Skipping test on this platform\n";
+    $tests += $basics;
+    $tests += $magic if $] >= 5.006;
+
+    if ( defined $ENV{TEST_LANGUAGES} ) {
+      if ( $ENV{TEST_LANGUAGES} eq "all" ) {
+	$tests += 2*$basics;
+	$tests += 2*$magic if $] >= 5.006;
+      } elsif ( $ENV{TEST_LANGUAGES} eq "EUC-JP"
+		or $ENV{TEST_LANGUAGES} eq "KOI8-R" ) {
+	$tests += $basics;
+	$tests += $magic if $] >= 5.006;
+      }
     }
-    else {
-        $tests += $basics;  
-        $tests += $magic if $] >= 5.006;
-
-        if ( defined $ENV{TEST_LANGUAGES} ) {
-            if ( $ENV{TEST_LANGUAGES} eq "all" ) {
-                $tests += 2*$basics;
-                $tests += 2*$magic if $] >= 5.006;
-            }
-            elsif ( $ENV{TEST_LANGUAGES} eq "EUC-JP"
-                    or $ENV{TEST_LANGUAGES} eq "KIO8-R" ) {
-                $tests += $basics;  
-                $tests += $magic-1 if $] >= 5.006;
-            }
-        }
-    }
-
     plan tests => $tests;
 }
 
-exit(0) unless $] < 5.008;
-
 use XML::LibXML::Common;
 use XML::LibXML;
 ok(1);
     my $elemlat1   = $dom_latin1->createElement( $tstr_iso_latin1 );
 
     $dom_latin1->setDocumentElement( $elemlat1 );
-    
+
     ok( decodeFromUTF8( 'iso-8859-1' ,$elemlat1->toString()),
         "<$tstr_iso_latin1/>");
     ok( $elemlat1->toString(0,1), "<$tstr_iso_latin1/>");
 
 }
 
-if ( $ENV{TEST_LANGUAGES} eq 'all' or $ENV{TEST_LANGUAGES} eq "KIO8-R" ) {
-    print "# cyrillic encoding (KIO8-R)\n";
+if ( $ENV{TEST_LANGUAGES} eq 'all' or $ENV{TEST_LANGUAGES} eq "KOI8-R" ) {
+    print "# cyrillic encoding (KOI8-R)\n";
 
-    my $tstr_kio8r       = '�����';
-    my $domstrkio = q{<?xml version="1.0" encoding="KIO8-R"?>
+    my $tstr_koi8r       = '�����';
+    my $domstrkoi = q{<?xml version="1.0" encoding="KOI8-R"?>
 <�����>�����</�����>
 };
     
 
     if ( $] >= 5.006 ) {
-        my ($dom_kio8, $elemkio8);
+        my ($dom_koi8, $elemkoi8);
 
-        $dom_kio8 = XML::LibXML::Document->new('1.0', 'KIO8-R');
-        $elemkio8 = $dom_kio8->createElement( $tstr_kio8r );
+        $dom_koi8 = XML::LibXML::Document->new('1.0', 'KOI8-R');
+        $elemkoi8 = $dom_koi8->createElement( $tstr_koi8r );
 
-        ok( decodeFromUTF8( 'KIO8-R' ,$elemkio8->nodeName()), 
-            $tstr_kio8r );
+        ok( decodeFromUTF8( 'KOI8-R' ,$elemkoi8->nodeName()), 
+            $tstr_koi8r );
 
-        ok( decodeFromUTF8( 'KIO8-R' ,$elemkio8->toString()), 
-            "<$tstr_kio8r/>");
-        ok( $elemkio8->toString(0,1), "<$tstr_kio8r/>");
+        ok( decodeFromUTF8( 'KOI8-R' ,$elemkoi8->toString()), 
+            "<$tstr_koi8r/>");
+        ok( $elemkoi8->toString(0,1), "<$tstr_koi8r/>");
 
-        $elemkio8->appendText( $tstr_kio8r );
+        $elemkoi8->appendText( $tstr_koi8r );
 
-        ok( decodeFromUTF8( 'KIO8-R' ,$elemkio8->string_value()),
-            $tstr_kio8r);
-        ok( $elemkio8->string_value(1),
-            $tstr_kio8r);
-        $dom_kio8->setDocumentElement( $elemkio8 );
+        ok( decodeFromUTF8( 'KOI8-R' ,$elemkoi8->string_value()),
+            $tstr_koi8r);
+        ok( $elemkoi8->string_value(1),
+            $tstr_koi8r);
+        $dom_koi8->setDocumentElement( $elemkoi8 );
 
-        ok( $dom_kio8->toString(),
-            $domstrkio );
+        ok( $dom_koi8->toString(),
+            $domstrkoi );
         
     }
 }