Commits

Anonymous committed f599a0e

Modified Files:
perl-libxml-sax.c LibXML.pm lib/XML/LibXML/SAX/Builder.pm
+ start_prefix_mapping
+ end_prefix_mapping

Comments (0)

Files changed (3)

     $parser->{HANDLER}->xml_decl($decl);
 }
 
+sub start_prefix_mapping {
+    my ( $parser, $prefix, $uri ) = @_;
+    $parser->{HANDLER}->start_prefix_mapping( { Prefix => $prefix, NamespaceURI => $uri } );
+}
+
+sub end_prefix_mapping {
+    my ( $parser, $prefix, $uri ) = @_;
+    $parser->{HANDLER}->end_prefix_mapping( { Prefix => $prefix, NamespaceURI => $uri } );
+}
+
 sub start_element {
     my (  $parser, $elem, $attrs ) = @_;
     my $saxattr = {};

lib/XML/LibXML/SAX/Builder.pm

 package XML::LibXML::SAX::Builder;
 
 use XML::LibXML;
+use XML::NamespaceSupport;
 
 sub new {
     my $class = shift;
         $self->xml_decl({Version => ($self->{Version} || '1.0') , Encoding => $self->{Encoding}});
     }
 
+    $self->{NamespaceStack} = XML::NamespaceSupport->new;
+    $self->{NamespaceStack}->push_context;
     $self->{Parent} = undef;
 }
 
     my ($self, $doc) = @_;
     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};
     return $dom;
 }
 
+sub start_prefix_mapping {
+    my $self = shift;
+    my $ns = shift;
+
+    $self->{NamespaceStack}->declare_prefix( $ns->{Prefix}, $ns->{NamespaceURI} );
+}
+
+
+sub end_prefix_mapping {
+    my $self = shift;
+    my $ns = shift;
+
+    $self->{NamespaceStack}->undeclare_prefix( $ns->{Prefix} );
+}
+
+
 sub start_element {
     my ($self, $el) = @_;
     my $node;
 
     unless ( defined $self->{DOM} or defined $self->{Parent} ) {
         $self->{Parent} = XML::LibXML::DocumentFragment->new();
+        $self->{NamespaceStack} = XML::NamespaceSupport->new;
+        $self->{NamespaceStack}->push_context;
     }
 
     if ($el->{NamespaceURI}) {
         }
         else {
             $node = XML::LibXML::Element->new( $el->{Name} );
-            $node->setNamespace( $el->{NamespaceURI},$el->{Prefix} , 1 );
+            $node->setNamespace( $el->{NamespaceURI},
+                                 $el->{Prefix} , 1 );
         }
     }
     else {
         }
     }
 
+    # build namespaces
+    foreach my $p ( $self->{NamespaceStack}->get_declared_prefixes() ) {
+        my $uri = $self->{NamespaceStack}->get_uri($p);
+        $node->setNamespace($uri, $p, $uri eq $el->{NamespaceURI} ? 1 : 0 );
+    }
+
     # append
     if ($self->{Parent}) {
         $self->{Parent}->appendChild($node);
         $self->{Parent} = $node;
     }
 
+     $self->{NamespaceStack}->push_context;
+
     # do attributes
     foreach my $key (keys %{$el->{Attributes}}) {
         my $attr = $el->{Attributes}->{$key};
         if (ref($attr)) {
-            if ( not defined $attr->{Prefix} or $attr->{Prefix} ne "xmlns" ) {
-                # SAX2 attributes
-                $node->setAttributeNS($attr->{NamespaceURI} || "",
-                                      $attr->{Name}, $attr->{Value});
-            }
-            else {
-                $node->setNamespace( $attr->{Value}, $attr->{LocalName},0 );
-            }
+            next if defined $attr->{Prefix} and $attr->{Prefix} eq "xmlns";
+            $node->setAttributeNS($attr->{NamespaceURI} || "",
+                                  $attr->{Name}, $attr->{Value});
         }
         else {
             $node->setAttribute($key => $attr);
 sub end_element {
     my ($self, $el) = @_;
     return unless $self->{Parent};
+
+    $self->{NamespaceStack}->pop_context;
     $self->{Parent} = $self->{Parent}->parentNode();
 }
 
     my ($self, $chars) = @_;
     if ( not defined $self->{DOM} and not defined $self->{Parent} ) {
         $self->{Parent} = XML::LibXML::DocumentFragment->new();
+        $self->{NamespaceStack} = XML::NamespaceSupport->new;
+        $self->{NamespaceStack}->push_context;
     }
     return unless $self->{Parent};
     $self->{Parent}->appendText($chars->{Data});
     my $comment;
     if ( not defined $self->{DOM} and not defined $self->{Parent} ) {
         $self->{Parent} = XML::LibXML::DocumentFragment->new();
+        $self->{NamespaceStack} = XML::NamespaceSupport->new;
+        $self->{NamespaceStack}->push_context;
     }
 
     if ( defined $self->{DOM} ) {
 sub error {
     my $self = shift;
     my $error = shift;
+    delete $self->{NamespaceStack};
     delete $self->{Parent};
     delete $self->{DOM};
     $error->throw;
 sub fatal_error {
     my $self = shift;
     my $error = shift;
+    delete $self->{NamespaceStack};
     delete $self->{Parent};
     delete $self->{DOM};
     $error->throw;

perl-libxml-sax.c

     xmlFree( vec );
 }
 
-void 
-PmmExtendNsStack( PmmSAXVectorPtr sax ) {
-    xmlNodePtr newNS = xmlNewDocNode( sax->ns_stack_root, NULL, "stack", NULL );
-    xmlAddChild(sax->ns_stack, newNS);
-    sax->ns_stack = newNS;
-}
-
-void
-PmmNarrowNsStack( PmmSAXVectorPtr sax ) {
-    xmlNodePtr parent = sax->ns_stack->parent;
-    xmlUnlinkNode(sax->ns_stack);
-    sax->ns_stack = parent;
-}
 
 xmlNsPtr
 PmmGetNsMapping( xmlNodePtr ns_stack, const xmlChar * prefix ) {
     return ret;
 }
 
+
+void
+PSaxStartPrefix( PmmSAXVectorPtr sax, const xmlChar * prefix, const xmlChar * uri )
+{
+    dTHX;
+    dSP;
+    
+    ENTER;
+    SAVETMPS;
+
+    PUSHMARK(SP) ;
+    XPUSHs(sax->parser);
+    if ( prefix != NULL ) {
+        XPUSHs( sv_2mortal( C2Sv(prefix, NULL) ) );
+    }
+    else {
+        XPUSHs( sv_2mortal( C2Sv("", NULL) ) );
+    }
+    XPUSHs( sv_2mortal( C2Sv(uri, NULL) ) );
+    PUTBACK;
+
+    perl_call_pv( "XML::LibXML::_SAXParser::start_prefix_mapping", 0 );
+
+    FREETMPS ;
+    LEAVE ;
+}
+
+void
+PSaxEndPrefix( PmmSAXVectorPtr sax, const xmlChar * prefix, const xmlChar * uri )
+{
+    dTHX;
+    dSP;
+    
+    ENTER;
+    SAVETMPS;
+
+    PUSHMARK(SP) ;
+    XPUSHs(sax->parser);
+    if ( prefix != NULL ) {
+        XPUSHs( sv_2mortal( C2Sv(prefix, NULL) ) );
+    }
+    else {
+        XPUSHs( sv_2mortal( C2Sv("", NULL) ) );
+    }
+    XPUSHs( sv_2mortal( C2Sv(uri, NULL) ) );
+    PUTBACK;
+
+    perl_call_pv( "XML::LibXML::_SAXParser::end_prefix_mapping", 0 );
+
+    FREETMPS ;
+    LEAVE ;
+}
+
+void 
+PmmExtendNsStack( PmmSAXVectorPtr sax ) {
+    xmlNodePtr newNS = xmlNewDocNode( sax->ns_stack_root, NULL, "stack", NULL );
+    xmlAddChild(sax->ns_stack, newNS);
+    sax->ns_stack = newNS;
+}
+
+void
+PmmNarrowNsStack( PmmSAXVectorPtr sax ) {
+    xmlNodePtr parent = sax->ns_stack->parent;
+    xmlNsPtr list = sax->ns_stack->nsDef;
+    while ( list ) {
+        if ( !xmlStrEqual(list->prefix, "xml") ) {
+            PSaxEndPrefix( sax, list->prefix, list->href );
+        }
+        list = list->next;
+    }
+    xmlUnlinkNode(sax->ns_stack);
+    sax->ns_stack = parent;
+}
+
+
 const xmlChar *
 PmmDetectNamespace( const xmlChar * name ) {
     const xmlChar *pos = xmlStrchr( name, (xmlChar)NSDELIM );
 }
 
 void
-PmmAddNamespace( xmlNodePtr ns_stack, const xmlChar * name, const xmlChar * href) {
-    if ( ns_stack != NULL ) {
+PmmAddNamespace( PmmSAXVectorPtr sax, const xmlChar * name, const xmlChar * href) {
+    if ( sax->ns_stack != NULL ) {
         xmlNsPtr ns = NULL;
         const xmlChar *pos = xmlStrchr( name, NSDELIM );
         xmlChar *decl= NULL;
             pos++;
             decl = xmlStrdup( pos );
             if ( decl != NULL && xmlStrlen( decl ) ) {
-                ns = xmlNewNs( ns_stack, href,decl );
+                ns = xmlNewNs( sax->ns_stack, href,decl );
             }
+         
+            PSaxStartPrefix( sax, decl, href );
             xmlFree( decl );
         }
         else {
-            ns = xmlNewNs( ns_stack, href, NULL );
+            ns = xmlNewNs( sax->ns_stack, href, NULL );
+            PSaxStartPrefix( sax, NULL, href );
         }
     }
 }
             hv_store(retval, "LocalName", 9,
                      C2Sv(name, NULL), LocalNameHash);
         }
-        
-        
+                
     }
     return retval;
 }
             if ( PmmDetectNamespaceDecl( *ta ) ) {
                 name = *ta; ta++;
                 value = *ta; ta++;
-                PmmAddNamespace(sax->ns_stack, name, value);                
+                PmmAddNamespace(sax, name, value);                
             }
             else {
                 ta++;ta++;
             atV = newHV();
             name = *ta; ta++;
             value = *ta; ta++;
-            
-            if ( name != NULL && xmlStrlen( name )  ) {
+            if (PmmDetectNamespaceDecl(name)) {
+                continue;
+            }
+            if ( name != NULL && xmlStrlen( name ) ) {
                 const xmlChar * pos = PmmDetectNamespace( name );
+
                 hv_store(atV, "Name", 4,
                          C2Sv(name, NULL), NameHash);
                 hv_store(atV, "Value", 5,
 
     return retval;
 }
+
 int
 PSaxStartDocument(void * ctx)
 {