Re: XML::LibXML - Mixing XPath with a document fragment

Petr Pajas <[email protected]>
Newsgroups gmane.comp.lang.perl.xml
Message-ID <[email protected]>
On čt 29. ledna 2009, Emmanuel Rodriguez wrote:
> Hi,
>
> I have an XML document that was generated with document fragments
> by an external function. This gave me some struggle because I was
> trying to use an XPath expression to access some nodes and
> couldn't reach them. This is due to the fact that even though the
> document fragment seems transparent it's still in the document
> and brakes the parent/child/sibling relation ship. This makes it
> a difficult to use XPath to search for nodes.
>
> Is there a way to clean document of all document fragments
> besides $xml =
> XML::LibXML->new()->parse_string($xml->toString()); ? Should
> document fragments be avoided?
>
> For the curious, I have attached a test case that shows the
> problems I had parsing the document.

Hallo Emmanuel!

A fragment node should never have appeared as a child of another 
node; that's the bug!

XML::LibXML should follow DOM spec [1], which says that attaching a 
document fragment to a node should result in moving the document 
fragment's children to the child list of the node, not in attaching 
the document fragment itself to the node. This seems to be a gap in 
XML::LibXML code, where addChild simply calls xmlAddChild without 
checking the node type; since xmlAddChild does not seem to do the 
job, I should add some code to handle fragments in a special way. 
addSibling seems to suffer from the same problem.

So the following part from your test case:

	# Add the child elements through a document fragment
	my $fragment = $xml->createDocumentFragment();
	$root->addChild($fragment);
	foreach my $id (1 .. 3) {
		my $node = XML::LibXML::Element->new('child');
		$node->setAttribute(id => $id);
		$fragment->addChild($node);
	}
	
should behave like a no-op, unless you rewrite it as

	# Add the child elements through a document fragment
	my $fragment = $xml->createDocumentFragment();
	foreach my $id (1 .. 3) {
		my $node = XML::LibXML::Element->new('child');
		$node->setAttribute(id => $id);
		$fragment->addChild($node);
	}
	$root->addChild($fragment);

in which case all nodes created inside the foreach loop and attached 
to the fragment should be re-attached to $root on 
$root->addChild($fragment), leaving the fragment empty.

I suggest you avoid calling addChild with a fragment as argument 
until XML::LibXML is fixed, which I'm gonna do now:-)

Thanks for pointing this out. Best,

[1] http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-B63ED1A3

-- Petr
_______________________________________________
Perl-XML mailing list
[email protected]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.