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, Petr Pajas wrote:
> 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!
oh, and the bug is documented:-)
addChild:
As an alternative to appendChild() one can use the addChild()
function. This function is a bit faster, because it avoids all DOM
conformity checks.
Well, in that case I might just add a simple node-type test and
croak on fragments (and possibly other invalid node types). That
will not cause any significant slow down.
One should use appendChild() for correct DOM behavior.
Best,
-- Petr
> 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
_______________________________________________
Perl-XML mailing list
[email protected]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs