in reply to copyCurrentNode in XML::LibXML::Reader will add xmlns attribute

I've had similar experiences with XML::LibXML, see my node here for a potential workaround (basically manually copying and re-creating the nodes instead of cloning).

Updated wording slightly for clarification.

  • Comment on Re: copyCurrentNode in XML::LibXML::Reader will add xmlns attribute

Replies are listed 'Best First'.
Re^2: copyCurrentNode in XML::LibXML::Reader will add xmlns attribute ( setNamespaceDeclURI )
by beech (Parson) on Sep 18, 2017 at 02:10 UTC

      Thanks, despite being marked "experimental" it does appear to work in the OP's case:

      use warnings; use strict; use XML::LibXML::Reader; my $xml = <<'ENDXML'; <foo xmlns="http://www.example.com"><bar/></foo> ENDXML my $reader = XML::LibXML::Reader->new(string => $xml); while ($reader->read) { my $node = $reader->copyCurrentNode; $node->setNamespaceDeclURI(undef, undef) if $node->nodeName eq 'bar'; print "$node"; } __END__ <foo xmlns="http://www.example.com"/><bar/><foo xmlns="http://www.exam +ple.com"/>

      Unfortunately I might still be missing something, because applied to choroba's code here it doesn't seem to change the namespace of the nodes.

        I don't get it. I experimented with $node->setNamespace(undef, undef, 1) which seems to be the simplest namespace handling fucntion, but I couldn't get it work.

        XML::LibXML defines setNamespace in the following way:

        sub setNamespace { my $self = shift; my $n = $self->nodeName; if ( $self->_setNamespace(@_) ){ if ( scalar @_ < 3 || $_[2] == 1 ){ $self->setNodeName( $n ); } return 1; } return 0; }

        where _setNamespace comes from its XS component, the important part (I guess) is the following:

        if ( nsPrefix == NULL && nsURI == NULL ) { /* special case: empty namespace */ if ( (ns = xmlSearchNs(node->doc, node, NULL)) && ( ns->href && xmlStrlen( ns->href ) != 0 ) ) { /* won't take it */ RETVAL = 0; } else if ( flag ) { /* no namespace */ xmlSetNs(node, NULL); RETVAL = 1; } else { RETVAL = 0; } }

        setNamespace returns 1, so I guess it goes the "else if" branch, but the namespace isn't removed from the node. xmlSetNs comes from libxml2 and is defined as (debugging ifdefs removed)

        void xmlSetNs(xmlNodePtr node, xmlNsPtr ns) { if (node == NULL) { return; } if ((node->type == XML_ELEMENT_NODE) || (node->type == XML_ATTRIBUTE_NODE)) node->ns = ns; }

        Anyone can explain why the namespace isn't changed?

        ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,