in reply to XML::Twig and namespaces

A test case would be helpful indeed, but I can try guessing.

ns_prefix returns a prefix for the element and that prefix is indeed bound in the XML document

Indeed, the prefix is bound in the XML document. But the newly created element is not part of a document. It's just a single detached element as far as XML::Twig is concerned. So it can't get the namespace information from its parent elements.

I have to think about it a bit, and see what other libraries do, because possible requirements are a bit hard to all satisfy:

At the moment you could probably get the namespace information by keeping a link to the original element in the copied document (stick it in an invisible attribute), and get the namespace info from it:

$copied->set_att( '#elt', $elt); my $namespace= $copied->att( '#elt')->namespace();

In fact I might well use something like that to solve the problem.

Replies are listed 'Best First'.
Re^2: XML::Twig and namespaces
by DJpumps (Novice) on Jul 04, 2007 at 09:36 UTC
    OK, the workaround works well for me:

    use strict; use warnings; use Data::Dumper; use XML::Twig; my $twig=XML::Twig->new(); $twig->xparse(shift); traverse($twig->root); sub traverse { my ($t) = @_; my $elt=$t; $elt=$t->att('#elt') if $t->att('#elt'); print "gi=|",$t->gi,"|\tprefix=|",$elt->ns_prefix,"|\tnamespac +e=|",$elt->namespace,"|\n"; foreach my $c ($t->children) { if (@ARGV) { my $copy = $c->copy; $copy->set_att( '#elt', $c); traverse($copy); } else { traverse($c); } } }

    I do think that the expected behavior in the case that I raised is that namespace information is kept. For those who don't want it -- it would be nice to have a method that will cause the elt to "forget" its namespace information.

    What do you think about this?

    Thanks again for your help and rapid response.

    By the way, while we're talking about namespace support in XML::Twig -- please notice that there are unexpected #default namespaces attached to attributes when using the map_xmlns option to the new method. I think this is caused by XML::Parser::Expat. How can one avoid getting this #default and get the namespace (the URN) instead? I think that getting the URN for default namespace makes more sense than getting #default. Moreover, the #default is returned for attributes which have no default namespace according to the w3c recommendation. Why is that?

    Thanks.

    -- DJpumps
Re^2: XML::Twig and namespaces
by DJpumps (Novice) on Jul 04, 2007 at 09:13 UTC
    Here's a test case:

    XML file:

    <?xml version="1.1"?>
    <a xmlns="default_ns_top">
            <b xmlns:foo="foo"/>
            <c xmlns:bar="bar"/>
            <d xmlns:baz="baz">
                    <e xmlns:lala="lala" xmlns:baz="baz2" xmlns="default_ns"/>
            </d>
    </a>
    
    

    a test perl script:

    
    use strict;
    use warnings;
    use Data::Dumper;
    use XML::Twig;
    
    my $twig=XML::Twig->new();
    $twig->xparse(shift);
    
    traverse($twig->root);
    
    
    sub traverse {
            my ($t) = @_;
            print "gi=|",$t->gi,"|\tprefix=|",$t->ns_prefix,"|\tnamespace=|",$t->namespace,"|\n";
            foreach my $c ($t->children) {
                    if (@ARGV) {
                            my $copy = $c->copy;
                            traverse($copy);
                    } else {
                            traverse($c);
                    }
            }
    }
    
    

    Notice the output when you run:

    $ perl test.pl test.xml # this is behaving OK
    

    But when you run it with a copy:

    $ perl test.pl test.xml copy # this is not OK
    

    You don't see a lot of namespace information.

    I'm going to try and use your proposed workaround.

    Thanks for your help.

    -- DJpumps