Re: Problem with namespaces in XML-LibXML-1.63
by Petr Pajas other posts by this author
Aug 13 2007 12:11PM messages near this date
view in the new Beta List Site
Problem with namespaces in XML-LibXML-1.63
|
Perl Bindings
& XSLT On Monday 13 August 2007, Steve Hay wrote:
> I've just upgraded from 1.58_01 to 1.63 and I've been bitten by a change
> of behaviour that was introduced in 1.62, namely, that
> $elt->cloneNode(0) now copies namespace information.
>
> Thus, the following program:
>
> use XML::LibXML;
> use XML::LibXML::XPathContext;
> my $parser = XML::LibXML->new();
> my $olddoc = $parser->parse_string(<<'EOX');
> <?xml version="1.0" encoding="UTF-8"?>
> <root xmlns="http://www.foo.org"/>
> EOX
> my $ctx = XML::LibXML::XPathContext->new();
> $ctx->registerNs('foo', 'http://www.foo.org');
> $ctx->setContextNode($olddoc);
> my($oldelt) = $ctx->findnodes('/foo:root');
> my $newelt = $oldelt->cloneNode(0);
> my $newdoc = XML::LibXML::Document->createDocument('1.0', 'UTF-8');
> $newdoc->setDocumentElement($newelt);
> print $newdoc->toString();
>
> now prints:
>
> <?xml version="1.0" encoding="UTF-8"?>
> <root xmlns="http://www.foo.org"/>
>
> whereas it used to print:
>
> <?xml version="1.0" encoding="UTF-8"?>
> <root/>
>
> I see in Node.pod that this is an intentional change for a good reason
> (and suitably documented too) so I'm not complaining about it, but I do
> need some way of getting the old behaviour, or something equivalent to
> it, back.
In such cases it seems more apropriate to create a new element and copying all
attributes by hand; anyway ... read below
> I'm copying an element from within a document that has an xmlns
> declaration in its document element, and making a new document out of
> it. The new document must not have any xmlns declaration when it is
> output, otherwise it'll break lots of XSL code further down the line.
>
> I had been using cloneNode(0) recursively (and copying any attributes
> present "manually") to achieve the desired behaviour, but as shown above
> I now find that cloneNode(0) copies the namespace too.
>
> I tried using the new setNamespaceDeclPrefix() on the copied element to
> try to clear its namespace:
>
> ...
> my $newelt = $oldelt->cloneNode(0);
> $newelt->setNamespaceDeclPrefix('foo', undef);
> ...
>
> but that gives me an error:
>
> setNamespaceDeclPrefix: prefix '(null)' is in use at test.pl line 13.
> Why does that cause an error?
Well, this seems ok to me. Your document is
<root xmlns="http://www.foo.org"/>
and the command above tries to turn a (non-existing) xmlns:foo="..."
declaration into xmlns="" (aka default namespace), but the void prefix is
already taken by http://www.foo.org. It would seem more natural if
XML::LibXML first detected that you in fact do not have any xmlns:foo="..."
declaration in your document and complain about that, but that's just an
implementation issue. The error messages tries to tell you that if your
document looked like
<root xmlns="http://www.foo.org" xmlns:foo="http://some.other.foo"/>
after a
$newelt-> setNamespaceDeclPrefix('foo', undef);
(if it didn't err) you would get,
<root xmlns="http://www.foo.org" xmlns="http://some.other.foo"/>
which is "ill-formed" XML.
> Is there some way to remove the xmlns
> using setNamespaceDeclPrefix() or setNamespaceDeclURI()?
Yes, you are supposed to do
$newelt-> setNamespaceDeclURI('',undef); # or (undef,undef)
which reads: undefine the namespace declaration for the empty prefix.
-- Petr
_______________________________________________
Perl-XML mailing list
Perl-XML@[...].com
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
Thread:
Steve Hay
Petr Pajas
|