Skip Menu |

This queue is for tickets about the XML-Compile CPAN distribution.

Report information
The Basics
Id: 76651
Status: resolved
Priority: 0/
Queue: XML-Compile

People
Owner: Nobody in particular
Requestors: andrew.vtk [...] gmail.com
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: 1.25
Fixed in: (no value)



Subject: problem with namespaces
I've got an error while trying to read document that has been produced with XML::Compile. I suppose that problem appears because there are no active namespaces for the xml nodes ( or I just have missed something ). Here is a short snippet demonstrating the problem: use XML::Compile::Cache; use XML::LibXML; my $s = XML::Compile::Cache->new( prefixes => { atk => 'http://example.com/2012/05/atk' } , key_rewrite => 'PREFIXED' ); my $schemas = XML::LibXML->load_xml( string => <<XML ); <?xml version="1.0"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" xmlns="http://example.com/2012/05/atk" targetNamespace="http://example.com/2012/05/atk" > <xsd:element name="test" type="xsd:string"/> </xsd:schema> XML $s->addSchemas( $schemas ); my $doc = XML::LibXML::Document->new( '1.0' ); my $writer = $s->compile('WRITER', 'atk:test' ); $doc->setDocumentElement( $writer->( $doc, "12" )); warn $doc->toString(2); my $reader = $s->compile('READER', 'atk:test' ); eval { # throws error $reader->( $doc ); }; # that's OK my $new_doc = XML::LibXML->load_xml( string => $doc->toString ); $reader->( $new_doc ); # what's the difference: # there is no namespace for the root node # warn $doc->documentElement->namespaceURI; # has it warn $new_doc->documentElement->namespaceURI; # has no
From: andrew.vtk [...] gmail.com
sorry, comments for the last two lines must be read as: $doc->documentElement->namespaceURI; # has no $new_doc->documentElement->namespaceURI; # has it i.e. $doc is broken, but $new_doc is OK since it has been converted to XML and passed through the libxml parser
Subject: Re: [rt.cpan.org #76651] problem with namespaces
Date: Wed, 18 Apr 2012 12:10:25 +0200
To: Andrey Tkachenko via RT <bug-XML-Compile [...] rt.cpan.org>
From: Mark Overmeer <mark [...] overmeer.net>
* Andrey Tkachenko via RT (bug-XML-Compile@rt.cpan.org) [120418 10:00]: Show quoted text
> Wed Apr 18 06:00:08 2012: Request 76651 was acted upon. > my $doc = XML::LibXML::Document->new( '1.0' ); > my $writer = $s->compile('WRITER', 'atk:test' ); > $doc->setDocumentElement( $writer->( $doc, "12" )); > > # throws error > $reader->( $doc );
I remember what the cause is. When an XML tree is being produced, I want to control the prefix of the node. However, there is no method to handle that in XML::LibXML (as far as I know)... I need something like this: $doc->createNode($prefix, $name, $value) but all I can do is $doc->createNode("$prefix:$name", $value) So, the created node is actually incorrect, therefore the reader doesn't like it. After a reparse of the XML message, the new node is correct. I have no idea how to fix this. The problem is documented somewhere. -- Regards, MarkOv ------------------------------------------------------------------------ Mark Overmeer MSc MARKOV Solutions Mark@Overmeer.net solutions@overmeer.net http://Mark.Overmeer.net http://solutions.overmeer.net
From: andrew.vtk [...] gmail.com
OK, I see. That's pity. I guess I'll use some kind of a dirty hack ( as I listed below ) to fix the problem. It slows down everything, of course :( ( even though there may be some caching etc.. ) Thanks. sub fix { my $node = shift; for my $ns ( $node->namespaces ) { my $name = $ns->getLocalName; $ns{ $name } = $ns->value; } if( $node->isa( 'XML::LibXML::Element' )) { if( !$node->namespaceURI and $node->nodeName =~ /:/ ) { my ( $prefix ) = $node->nodeName =~ /^([^:]+):/; warn "patching $prefix ( ". $node->nodeName ; if( my $v = $ns{ $prefix }) { $node->setNamespace( $v, $prefix, 1 ); } } } fix( $_ ) for $node->childNodes; } fix( $doc->documentElement );
Subject: Re: [rt.cpan.org #76651] problem with namespaces
Date: Wed, 18 Apr 2012 13:55:34 +0200
To: Andrey Tkachenko via RT <bug-XML-Compile [...] rt.cpan.org>
From: Mark Overmeer <mark [...] overmeer.net>
* Andrey Tkachenko via RT (bug-XML-Compile@rt.cpan.org) [120418 11:24]: Show quoted text
> Queue: XML-Compile > Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=76651 > > > if( !$node->namespaceURI and $node->nodeName =~ /:/ ) { > my ( $prefix ) = $node->nodeName =~ /^([^:]+):/; > warn "patching $prefix ( ". $node->nodeName ; > if( my $v = $ns{ $prefix }) { > $node->setNamespace( $v, $prefix, 1 );
Doesn't this add namespace declarations to the nodes? There are only three places in XML/Compile/Translate/Writer where createElement is being called. We may be able to call setNamespace there to fix this issue... but I am a bit worried the output would change (get more verbose) -- Regards, MarkOv ------------------------------------------------------------------------ Mark Overmeer MSc MARKOV Solutions Mark@Overmeer.net solutions@overmeer.net http://Mark.Overmeer.net http://solutions.overmeer.net
From: andrew.vtk [...] gmail.com
As I see from XML::LibXML::Element man, they try to re-use namespace declarations for the nodes. setNamespace $node->setNamespace( $nsURI , $nsPrefix, $activate ); setNamespace() allows one to apply a namespace to an element. The function takes three parameters: 1. the namespace URI, which is required and the two optional values prefix, which is the namespace prefix, as it should be used in child elements or attributes as well as the additional activate parameter. If prefix is not given, undefined or empty, this function tries to create a declaration of the default namespace. The activate parameter is most useful: If this parameter is set to FALSE (0), a new namespace declaration is simply added to the element while the element's namespace itself is not altered. Nevertheless, activate is set to TRUE (1) on default. In this case the namespace is used as the node's effective namespace. This means the namespace prefix is added to the node name and if there was a namespace already active for the node, it will be replaced (but its declaration is not removed from the document). A new namespace declaration is only created if necessary (that is, if the element is already in the scope of a namespace declaration associating the prefix with the namespace URI, then this declara‐ tion is reused).
From: andrew.vtk [...] gmail.com
Here it is: A new namespace declaration is only created if necessary (that is, if the element is already in the scope of a namespace declaration associating the prefix with the namespace URI, then this declara‐ tion is reused).
Subject: Re: [rt.cpan.org #76651] problem with namespaces
Date: Wed, 18 Apr 2012 14:57:48 +0200
To: Andrey Tkachenko via RT <bug-XML-Compile [...] rt.cpan.org>
From: Mark Overmeer <secretaris [...] nluug.nl>
* Andrey Tkachenko via RT (bug-XML-Compile@rt.cpan.org) [120418 12:04]: Show quoted text
> Queue: XML-Compile > Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=76651 > > > A new namespace declaration is only created if necessary (that is, if > the element is already in the scope of a namespace declaration > associating the prefix with the namespace URI, then this declara‐ tion > is reused).
The XML messages are constructed from bottom to up... so on each level this will probably recreate the declaration. When the messages gets constructed top-down this feature would work :( #!/usr/bin/env perl use XML::LibXML; my $doc = XML::LibXML::Document->new('1.0', 'UTF-8'); my $ns = 'http://example.com'; my $one = $doc->createElementNS($ns, 'one'); my $two = $doc->createElementNS($ns, 'two'); $one->addChild($two); $doc->setDocumentElement($one); print $doc->toString(1); -- Regards, MarkOv ------------------------------------------------------------------------ Mark Overmeer MSc MARKOV Solutions Mark@Overmeer.net solutions@overmeer.net http://Mark.Overmeer.net http://solutions.overmeer.net
From: andrew.vtk [...] gmail.com
If you replace 'addChild' with 'appendChild' in your example, all the things would work OK. As it said in XML::LibXML::Node doc, addChild is a libxml2 specific function. It works faster than appendChild, but has some side effects.. Thus, appendChild is a bit slower, but it is a DOM-conformant ( it slower than addCHild just because it makes some extra things - including the ones we need )
From: andrew.vtk [...] gmail.com
If we need to control prefixes, then use XML::LibXML; my $doc = XML::LibXML::Document->new('1.0', 'UTF-8'); my $ns1 = 'http://example.com'; my $ns2 = 'http://example.com/2'; my $one = $doc->createElementNS($ns1, 'ns1:one'); $one->setNamespace( $ns1, 'ns1', 0 ); my $two = $doc->createElementNS($ns2, 'ns2:two'); $two->setNamespace( $ns2, 'ns2', 0 ); $one->setNamespace( $ns2, 'ns2', 0 ); $one->appendChild($two); $doc->setDocumentElement($one); print $doc->toString(1); Of course, this requires some extra efforts for declaring namespaces in a top element before adding child one. Or may be there is another way to play with prefixes
Subject: Re: [rt.cpan.org #76651] problem with namespaces
Date: Wed, 18 Apr 2012 16:51:46 +0200
To: Andrey Tkachenko via RT <bug-XML-Compile [...] rt.cpan.org>
From: Mark Overmeer <mark [...] overmeer.net>
* Andrey Tkachenko via RT (bug-XML-Compile@rt.cpan.org) [120418 14:42]: Show quoted text
> Queue: XML-Compile > Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=76651 > > > Of course, this requires some extra efforts for declaring namespaces in > a top element before adding child one.
And that is exactly the problem: this is frustrated by the recursive nature of the implementation: there is no overview. Show quoted text
> Or may be there is another way to play with prefixes
... waiting for that ;-) Of course, I could provide people with the cleanup along the lines of your example. Although i think it is faster and safer to simply do $clone = XML::LibXML::Parser->load_xml(string => $doc->toString); -- Regards, MarkOv ------------------------------------------------------------------------ Mark Overmeer MSc MARKOV Solutions Mark@Overmeer.net solutions@overmeer.net http://Mark.Overmeer.net http://solutions.overmeer.net
From: andrew.vtk [...] gmail.com
Ok, probably you are right. Thanks for the quick and kind feedback :)
closed