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