List Info

Thread: Problem with namespaces in XML-LibXML-1.63




Problem with namespaces in XML-LibXML-1.63
user name
2007-08-13 10:38:16
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:ocument-
>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.

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? Is there some way to remove
the xmlns
using setNamespaceDeclPrefix() or setNamespaceDeclURI()?
_______________________________________________
Perl-XML mailing list
Perl-XMLlistserv.ActiveState.com
To unsubscribe: http:/
/listserv.ActiveState.com/mailman/mysubs

Re: Problem with namespaces in XML-LibXML-1.63
country flaguser name
Czech Republic
2007-08-13 13:37:06
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:ocument-
>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.fo
o"/>

after a

$newelt->setNamespaceDeclPrefix('foo', undef);

(if it didn't err) you would get, 

<root xmlns="http://www.foo.org"
xmlns="http://some.other.fo
o"/>

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-XMLlistserv.ActiveState.com
To unsubscribe: http:/
/listserv.ActiveState.com/mailman/mysubs

RE: Problem with namespaces in XML-LibXML-1.63
user name
2007-08-14 03:19:08
Petr Pajas wrote:
> 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.
>> 
>> 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

The real code, of course, is doing much more than the simple
example
that I posted. The element being copied has a great many
descendants,
with and without attributes, so it would require a recursive
procedure
exactly like cloneNode(), except without the
namespace-copying...


>> 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. 

Ah, OK. I was thinking that the registerNs('foo', 'http://www.foo.org')
call that I did earlier would mean that the URI http://www.foo.org was
now associated with the 'foo' prefix rather than the null
prefix, hence
it was the 'foo' prefix that I was using to try to clear the
namespace.

Just to be clear: does that registerNs() call in fact mean
that *both*
the 'foo' prefix and the null prefix are now associated
with
http://www.foo.org, i.e. as
if my document looked lik:

<root xmlns="http://www.foo.org"
xmlns:foo="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.fo
o"/>
> 
> after a
> 
> $newelt->setNamespaceDeclPrefix('foo', undef);
> 
> (if it didn't err) you would get,
> 
> <root xmlns="http://www.foo.org"
xmlns="http://some.other.fo
o"/>
> 
> which is "ill-formed" XML.

Right, I understand now.


> 
>> 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.

Got it.

Many thanks.
_______________________________________________
Perl-XML mailing list
Perl-XMLlistserv.ActiveState.com
To unsubscribe: http:/
/listserv.ActiveState.com/mailman/mysubs

Re: Problem with namespaces in XML-LibXML-1.63
country flaguser name
Czech Republic
2007-08-14 03:12:40
On Tuesday 14 August 2007, Steve Hay wrote:
> Petr Pajas wrote:
> > 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.
> >>
> >> 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
>
> The real code, of course, is doing much more than the
simple example
> that I posted. The element being copied has a great
many descendants,
> with and without attributes, so it would require a
recursive procedure
> exactly like cloneNode(), except without the
namespace-copying...

still, that seems to me the right way to do such a thing.

> >> 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.
>
> Ah, OK. I was thinking that the registerNs('foo', 'http://www.foo.org')
> call that I did earlier would mean that the URI http://www.foo.org was
> now associated with the 'foo' prefix rather than the
null prefix, hence
> it was the 'foo' prefix that I was using to try to
clear the namespace.
>
> Just to be clear: does that registerNs() call in fact
mean that *both*
> the 'foo' prefix and the null prefix are now associated
with
> http://www.foo.org,
i.e. as if my document looked lik:
>
> <root xmlns="http://www.foo.org"
xmlns:foo="http://www.foo.org"
;/>
>
> ?

No, registerNs is a method of XPathContext. It allows you to
refer to a 
particular namespace using a prefix in XPath expressions
evaluated in that 
context. It has nothing to do with DOM processing.

-- Petr
_______________________________________________
Perl-XML mailing list
Perl-XMLlistserv.ActiveState.com
To unsubscribe: http:/
/listserv.ActiveState.com/mailman/mysubs

RE: Problem with namespaces in XML-LibXML-1.63
country flaguser name
United Kingdom
2007-08-14 03:55:10
> -----Original Message-----
> From: perl-xml-bounceslistserv.ActiveState.com 
> 
> On Tuesday 14 August 2007, Steve Hay wrote:
> > Petr Pajas wrote:
> > > 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.
> > >>
> > >> 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
> >
> > The real code, of course, is doing much more than
the simple example
> > that I posted. The element being copied has a
great many 
> descendants,
> > with and without attributes, so it would require a

> recursive procedure
> > exactly like cloneNode(), except without the
namespace-copying...
> 
> still, that seems to me the right way to do such a
thing.

My immmediate thought on this was it is it a serialisation
issue.

I couldn't find a SAX writer that strips namespaces, but I
suspect you could
write a subclass of XML::SAX::Writer that could do the job.

Cheers,
Tim.



_______________________________________________
Perl-XML mailing list
Perl-XMLlistserv.ActiveState.com
To unsubscribe: http:/
/listserv.ActiveState.com/mailman/mysubs

Re: Problem with namespaces in XML-LibXML-1.63
country flaguser name
Germany
2007-08-16 14:39:17
* Steve Hay <SteveHayplanit.com> [2007-05-22
14:45]:
> The real code, of course, is doing much more than the
simple
> example that I posted. The element being copied has a
great
> many descendants, with and without attributes, so it
would
> require a recursive procedure exactly like cloneNode(),
except
> without the namespace-copying...

If all you are doing is munging the XML, then write an XSLT
transform do it instead. It’s much easier to do it that
way
anyway. If you are doing more than just rearranging the XML,
which couldn’t be done in XSLT, then do the namespace
stripping
in an extra transform step… the transform to do is so
simple that
you’ll wind up writing much less code despite the extra
fooflah
required to set up LibXSLT for the transformation, and it
will
be more robust.

Regards,
-- 
Aristotle Pagaltzis // <http://plasmasturm.org/&g
t;
_______________________________________________
Perl-XML mailing list
Perl-XMLlistserv.ActiveState.com
To unsubscribe: http:/
/listserv.ActiveState.com/mailman/mysubs
[1-6]

about | contact  Other archives ( Real Estate discussion Medical topics )