CraigP
CraigP

Reputation: 453

Perl LibXML - InsertAfter / addSibling

I'm trying to simply add a block of xml code (from parsed_balance_chunk), testing the effects of attempting to add a child and as sibling. I'm playing around wih both "insertAfter" & "addSibling" and testing how to insert the fragment in different sections of the xml. With the "insertAfter" (and for that matter "insertBefore"), it adds it as last children of "C". 1.) How can I get it to insert as first child of "C" (i.e. before "D")? 2.) With another test, how can I get it to be a sibling of "C"? When I try "addSibling", it spits back a message saying 'adding document fragments with addSibling not yet supported!'.

Also, with the definition of $frag, if I define it outside the foreach look, it only adds the $frag to the first node (and not the 2nd occurance of "C").

Code:

use warnings;
use strict;
use XML::LibXML;
use Data::Dumper;

my $parser = XML::LibXML->new({keep_blanks=>(0)});
my $dom = $parser->load_xml(location => 'test_in.xml') or die;

my @nodes = $dom->findnodes('//E/../..');

foreach my $node (@nodes)
{
 my $frag = $parser->parse_balanced_chunk ("<YY>yyy</YY><ZZ>zz</ZZ>");
 $node->insertBefore($frag, undef);
 #$node->addSibling($frag);
}

open my $FH, '>', 'test_out.xml';
print {$FH} $dom->toString(1);
close ($FH);

Input File:

<?xml version="1.0"?>
<TT>
 <A>ZAB</A>
 <B>ZBW</B>
 <C>
  <D>
   <E>ZSE</E>
   <F>ZLC</F>
  </D>
 </C>
 <C>
  <D>
   <E>one</E>       
  </D>
 </C>
</TT>

Output File:

<?xml version="1.0"?>
<TT>
  <A>ZAB</A>
  <B>ZBW</B>
  <C>
    <D>
      <E>ZSE</E>
      <F>ZLC</F>
    </D>
    <YY>yyy</YY>
    <ZZ>zz</ZZ>
  </C>
  <C>
    <D>   
      <E>one</E>
    </D>
    <YY>yyy</YY>
    <ZZ>zz</ZZ>
  </C>
</TT>

Upvotes: 2

Views: 1503

Answers (2)

choroba
choroba

Reputation: 242083

#1
$node->insertBefore($frag, $node->firstChild);
#2
$node->parentNode->insertAfter($frag, $node);

Upvotes: 1

Tim Peoples
Tim Peoples

Reputation: 354

From the documentation for XML::LibXML::Node->insertNode($newNode, $refNode):

The method inserts $newNode before $refNode. If $refNode is
undefined, the newNode will be set as the new last child of the
parent node.  This function differs from the DOM L2 specification,
in the case, if the new node is not part of the document, the node
will be imported first, automatically.

...so, if you want it inserted as the new first child, you'll need to get a handle on the current first child node, like so:

$node->insertBefore($frag, $node->firstChild);

Upvotes: 2

Related Questions