http://www.perlmonks.org?node_id=464408


in reply to Manipulate xml with libxml

I was a little confused so I must assume that the first instance of <fixe> is not truly your root element. Yet, even with my assumptions, this may help. I added the passing of $it (iteration) and $nn (node name).

Try this:
#!/usr/bin/perl -w -s use strict; use XML::LibXML; my $it = shift || 1; my $nn = shift || ''; print qq($it\n); my $parser = XML::LibXML->new(); my $doc = $parser->parse_file("model.xml") or die "cannot open xml fil +e: $!"; my $node = $doc->getDocumentElement(); my @dc = $node->getElementsByTagName('fixe'); foreach my $descr (@dc) { foreach my $elt ($descr->childNodes()) { next unless $elt->nodeType() == 1; #to avoid text nodes if ( $elt->nodeName eq $nn ) { $descr->addSibling($elt->cloneNode) foreach ( 1 .. $it ); } else { $descr->addSibling($elt); } } my $parent = $descr->parentNode; $parent->removeChild($descr); } print $doc->toString();
XML is very particular in that an element is an element, it already exists. Your were on the right track with cloneNode, you just needed to combine that with the appendSibling.

Don
WHITEPAGES.COM | INC

Edit by castaway: Closed small tag in signature

Replies are listed 'Best First'.
Re^2: Manipulate xml with libxml
by Anonymous Monk on Jun 08, 2005 at 09:20 UTC
    Thank you very much Don!! It works well. I am happy.

    I just added the argument 1 with the cloneNode function to get the child nodes.
    $descr->addSibling($elt->cloneNode(1))
    You are right, <fixe> is not the root element of the file. I should have mentioned that.

    by the way, when I remove some nodes and then when I use toString or serialize, the xml is not really pretty. Is there a function to remove unneeded \n and to format the output with the good indentation? (a kind of "pretty print" with xmlspy for those who know this software)
      I confess LibXML doesn't create pretty XML, in fact I normally include variables to strip out the unneccesary whitespace because I send it through XSLT. You can write some kind recursive loop to fix it all or if you are not to worried about speed, send your string to XML::Twig. It has some great pretty_print functionality. I only make the comment about speed because in this you will be effectively parsing your XML twice.

      Don
      WHITEPAGES.COM | INC

      Edit by castaway: Closed small tag in signature

        As much as it pains me to say this ;--( ... if libxml2 is installed, it might be just as simple to use xmllint --format. And XML::Twig comes with a standalone tool: xml_pp.

Re^2: Manipulate xml with libxml
by Anonymous Monk on Jun 08, 2005 at 12:13 UTC
    Hum...I suspect a problem of recursivity if I put cloneNode(1)
    because when the first motif become a sibbling, the others one inside with the same motif are not treated yet.
    it is more complicated in fact