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


in reply to Re^2: how to update an xml file by read data from csv file
in thread how to update an xml file by read data from csv file

Here's a solution that uses XML::TreeBuilder (which uses XML::Element methods as well). It seemed easier than trying to build it up from print statements and regex replacements.

One maybe major caveat: your example input file isn't valid XML-- the two "container" tags don't get closed. I took the liberty of assuming (maybe incorrectly) that they should get closed and that you want valid XML.

Here's the code:
#!/usr/bin/perl use warnings; use strict; use Text::CSV; use XML::TreeBuilder; use Data::Dumper; my $xmlbase='original.xml'; my $paramsfile = 'params.csv'; # the list of tags filled from the csv file my @taglist=qw(name protocol host commandline); # this is the part that repeats, so we break it out separately # the tags that get filled from the CSV file are left empty my $connection= <<END <connection type="PuTTY" name="WSSS"> <connection_info> <name></name> <protocol></protocol> <host></host> <port>22</port> <session>Default Settings</session> <commandline></commandline> <description /> </connection_info> <login> <login /> <password /> <prompt /> </login> <timeout> <connectiontimeout>1000</connectiontimeout> <logintimeout>750</logintimeout> <passwordtimeout>750</passwordtimeout> <commandtimeout>750</commandtimeout> </timeout> <command> <command1 /> <command2 /> <command3 /> <command4 /> <command5 /> </command> <options> <loginmacro>False</loginmacro> <postcommands>False</postcommands> <endlinechar>10</endlinechar> </options> </connection> END ; #this is the wrapper my $config= <<END <?xml version="1.0" encoding="UTF-8"?> <!-- The following lines can be modified at your own risks. --> <configuration version="0.2.1.4" savepassword="True"> <root type="database" name="WSSS" expanded="True"> <container type="folder" name="CM" expanded="True"> <container type="folder" name="1-AD/M" expanded="True"> </container> </container> </root> </configuration> END ; #start an xml structure with the outer wrapper my $tree=XML::TreeBuilder->new(); $tree->parse($config); # find the insert location my $container=$tree->look_down("_tag"=>"container", "name"=>"1-AD/M"); + my $csv=Text::CSV->new(); open my $fh, "<:encoding(utf8)", $paramsfile or die "$paramsfile: $!"; # loop through the lines of the CSV and copy the connection structure +into # the wrapper with the updated values while(my $row=$csv->getline($fh)){ my $contree=XML::TreeBuilder->new(); #make an xml structure of th +e connection $contree->parse($connection); $container->push_content($contree); #insert it into the wrapper $contree->attr('name',$row->[0]); #set the name attribute $container->push_content("\n "); #make it a little prettier my $index=0; for my $tagname(@taglist){ #loop through the columns my $tag=$contree->look_down('_tag'=> $tagname); $tag->push_content($row->[$index++]); } } print '<?xml version="1.0" encoding="UTF-8"?>'."\n"; print $tree->as_XML();
And here's the output:
$ perl puttyconfig.pl <?xml version="1.0" encoding="UTF-8"?> <configuration savepassword="True" version="0.2.1.4"> <root expanded="True" name="WSSS" type="database"> <container expanded="True" name="CM" type="folder"> <container expanded="True" name="1-AD/M" type="folder"> <connection name="WSSSS" type="PuTTY"> <connection_info> <name>WSSSS</name> <protocol>SSH</protocol> <host>103.243.543.233</host> <port>22</port> <session>Default Settings</session> <commandline>erted</commandline> <description></description> </connection_info> <login> <login></login> <password></password> <prompt></prompt> </login> <timeout> <connectiontimeout>1000</connectiontimeout> <logintimeout>750</logintimeout> <passwordtimeout>750</passwordtimeout> <commandtimeout>750</commandtimeout> </timeout> <command> <command1></command1> <command2></command2> <command3></command3> <command4></command4> <command5></command5> </command> <options> <loginmacro>False</loginmacro> <postcommands>False</postcommands> <endlinechar>10</endlinechar> </options> </connection> <connection name="AWSA" type="PuTTY"> <connection_info> <name>AWSA</name> <protocol>SSH</protocol> <host>303.233.542.622</host> <port>22</port> <session>Default Settings</session> <commandline>rrertd</commandline> <description></description> </connection_info> <login> <login></login> <password></password> <prompt></prompt> </login> <timeout> <connectiontimeout>1000</connectiontimeout> <logintimeout>750</logintimeout> <passwordtimeout>750</passwordtimeout> <commandtimeout>750</commandtimeout> </timeout> <command> <command1></command1> <command2></command2> <command3></command3> <command4></command4> <command5></command5> </command> <options> <loginmacro>False</loginmacro> <postcommands>False</postcommands> <endlinechar>10</endlinechar> </options> </connection> </container> </container> </root> </configuration>