Maxim has asked for the wisdom of the Perl Monks concerning the following question:

Hi all,

I am using the module XML::LibXML to cut and paste. I can copy the node I want and erase it after. When I want to paste into another node, it doesn't insert. I don't know why it doesn't insert.
I want to insert the node product "800.55.01" to the node of "Grand Abrica".

Here the code and the data.
use XML::LibXML; use warnings; use strict; my $copy = ''; my $lastnode = ''; my $file = (<DATA>); #UPDATE my $d = XML::LibXML->new->parse_file(join "", $file); &copy; &paste; $d->toFile('c:\test1.xml'); sub copy { for my $dead ($d->findnodes(q{/category/subcategory/product[pr +oduct_id = "800.55.01"]})) { #copy the node before it die $copy = $dead->cloneNode; #the node die $dead->unbindNode; } } sub paste { for my $paste ($d->findnodes(q{/category/subcategory[@name = " +Grand Arabica"]})) { my $curcopy = $copy; $lastnode = $paste->lastChild; $paste->insertAfter($lastnode, $curcopy); } } __DATA__ <category> <subcategory name="Prestige"> <comments><paragraph>Prestige is a very traditional French + recipe: a blend of Robusta and Arabica beans. The Robusta is known f +or its strength and the Arabica for its delicate flavour. The Prestig +e is the ideal coffee for Espresso. The 500gr come in the re-usable A +roma Box especially designed to preserve the freshness and aroma of y +our coffee.</paragraph> </comments> <photo>images/prestige.jpg</photo> <product>Coffee <channel>D</channel> <channel>A</channel> <product_id>800.55.01</product_id> <brand>Legal</brand> <description>Legal Prestige</description> <conditionning unit="gr">250</conditionning> <packaging_qty>12</packaging_qty> <recipe>/recipes/coffee1.html</recipe> </product> <product>Coffee <channel>D</channel> <channel>A</channel> <product_id>801.55.01</product_id> <brand>Legal</brand> <description>Legal Prestige Boite Ar&#xF4;me</descript +ion> <conditionning unit="gr">500</conditionning> <packaging_qty>6</packaging_qty> </product> </subcategory> <subcategory name="Grand Arabica"> <comments><paragraph>Experience the subtle voluptuousness +of extraordinary Arabica coffee in your cup. Grand Arabica: incompara +ble pleasure in coffee.</paragraph></comments> <photo>images/arabica.jpg</photo> <product>Coffee <channel>A</channel> <channel>D</channel> <channel>S</channel> <product_id>802.55.01</product_id> <brand>Legal</brand> <description>Grand Arabica</description> <conditionning unit="gr">250</conditionning> <packaging_qty>12</packaging_qty> </product> </subcategory> </category>


Thanks in advance

Maxim

Replies are listed 'Best First'.
Re: XML::LibXML cut and paste node
by kvale (Monsignor) on Oct 19, 2004 at 16:02 UTC
    Please note that your code as submitted does not work -- there is no test1.xml. I rewrote it to use <DATA>.

    The main problem is that cloneNode only makes a shallow copy; in fact you can still use the node $dead after it is unbound and it still contains all the child info. Here is my rewritten program:

    #!/usr/bin/perl -w use strict; use XML::LibXML; my $parser = XML::LibXML->new(); my $doc = $parser->parse_string(join "", <DATA>); # copy the node, then delete it my $from_path = q{/category/subcategory/product[product_id = "800.55.0 +1"]}; my @from_nodes = $doc->findnodes( $from_path); my $dead = $from_nodes[0]; # Assume there can be only one $dead->unbindNode; # paste the node to a new location my $to_path = q{/category/subcategory[@name = "Grand Arabica"]}; my @to_nodes = $doc->findnodes( $to_path); my $paste = $to_nodes[0]; # Assume there can be only one my $lastnode = $paste->lastChild(); $paste->insertAfter( $dead, $lastnode); print $doc->toString([0]);

    -Mark

      From the documentation, it said it will make a copy of the node. I thought it will be useful to use this command. Anyway, thanks for your help. It will really help me.

      Regard,

      Maxim
      From the example you gave me, it works perfectly but when I put a variable to indentify the correct value what I want, it gives an error "xmlXPathCompiledEval: 1 object left on the stack".
      Here an emaple using ur example I change this my $from_path = q{/category/subcategory/product[product_id = "800.55.01"]}; to this my $from_path = q{/category/subcategory/product[product_id = $prod]};. It will show the error message.

      Is a problem with the stack?

      Maxim