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

Hi Monks,

I have a question to ask you. Since I am building a web site using XML as a database. I am wondering with XML modules if we can cut some elements from a child node and paste to another child node in the XML file. I am using XML::Simple but I found, it has some limitation. Is there a module you recomend?

Here an example, I want to move the product ID "800.55.01" to the subcategory "Grand Arabica". (Original data)
__DATA__ <category> <subcategory name="Prestige"> <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"> <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

Maxim

Replies are listed 'Best First'.
Re: XML cut and paste
by Fletch (Bishop) on Oct 17, 2004 at 13:36 UTC

    XML::Twig lets you move chunks of your XML tree ("twigs") around. This article from ORA's xml.com provides a pretty good introduction to the module.

Re: XML cut and paste
by steves (Curate) on Oct 17, 2004 at 12:25 UTC

    You should be able to manipulate the hash XML::Simple creates from your data, then write the modified verion back out using its XMLout method. Have you tried that and is that where you hit the limitation? If so, it might be helpful to see that code.

Re: XML cut and paste
by pg (Canon) on Oct 17, 2004 at 18:18 UTC

    XML::Simple is good enough in this case. Most likely you do't know what the data structure should look like after you moved the product id around, in terms of how XML::Simple wants it to be. That is easy, do a copy and paste manually, read in those two files, one with product id at its current place, and one with product id at the place you want, observe carefully the difference, then you will know how.

      I followed what I said to you, and here is the code, and result:

      use XML::Simple; use Data::Dumper; use strict; use warnings; my $ref = XMLin("test1.xml"); my $subcats = $ref->{'subcategory'}; for my $subcat (keys(%$subcats)) { my $id; my $products = $subcats->{$subcat}->{'product'}; if (ref($products) eq 'ARRAY') { $id = $products->[0]->{'product_id'}; for (0 .. $#{@$products}) { delete $products->[$_]->{'product_id'}; } } elsif (ref($products) eq 'HASH') { $id = $products->{'product_id'}; delete $products->{'product_id'}; } $subcats->{$subcat}->{'product_id'} = $id; } my $xml = XMLout($ref, KeepRoot=>1, NoAttr => 1); print $xml;
      <subcategory> <Grand Arabica> <photo>images/arabica.jpg</photo> <product> <brand>Legal</brand> <channel>A</channel> <channel>D</channel> <channel>S</channel> <conditionning> <content>250</content> <unit>gr</unit> </conditionning> <content>Coffee </content> <description>Grand Arabica</description> <packaging_qty>12</packaging_qty> </product> <product_id>802.55.01</product_id> </Grand Arabica> <Prestige> <photo>images/prestige.jpg</photo> <product> <brand>Legal</brand> <channel>D</channel> <channel>A</channel> <conditionning> <content>250</content> <unit>gr</unit> </conditionning> <content>Coffee </content> <description>Legal Prestige</description> <packaging_qty>12</packaging_qty> <recipe>/recipes/coffee1.html</recipe> </product> <product> <brand>Legal</brand> <channel>D</channel> <channel>A</channel> <conditionning> <content>500</content> <unit>gr</unit> </conditionning> <content>Coffee </content> <description>Legal Prestige Boite Arôme</description> <packaging_qty>6</packaging_qty> </product> <product_id>800.55.01</product_id> </Prestige> </subcategory>
        What you gave e, it doesn't move the product id "800.55.01" to the subcategory "Grand Abrica". I am trying now to use XML::twig, which I found an useful example from the documentation. Thanks by the way to help me.

        Maxim