<?xml version="1.0" encoding="windows-1252"?>
<node id="1006444" title="Re^3: how to update an xml file by read data from csv file" created="2012-11-30 05:00:17" updated="2012-11-30 05:00:17">
<type id="11">
note</type>
<author id="424801">
bitingduck</author>
<data>
<field name="doctext">
&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;
Here's the code:
&lt;code&gt;
#!/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= &lt;&lt;END
        &lt;connection type="PuTTY" name="WSSS"&gt;
          &lt;connection_info&gt;
            &lt;name&gt;&lt;/name&gt;
            &lt;protocol&gt;&lt;/protocol&gt;
            &lt;host&gt;&lt;/host&gt;
            &lt;port&gt;22&lt;/port&gt;
            &lt;session&gt;Default Settings&lt;/session&gt;
            &lt;commandline&gt;&lt;/commandline&gt;
            &lt;description /&gt;
          &lt;/connection_info&gt;
          &lt;login&gt;
            &lt;login /&gt;
            &lt;password /&gt;
            &lt;prompt /&gt;
          &lt;/login&gt;
          &lt;timeout&gt;
            &lt;connectiontimeout&gt;1000&lt;/connectiontimeout&gt;
            &lt;logintimeout&gt;750&lt;/logintimeout&gt;
            &lt;passwordtimeout&gt;750&lt;/passwordtimeout&gt;
            &lt;commandtimeout&gt;750&lt;/commandtimeout&gt;
          &lt;/timeout&gt;
          &lt;command&gt;
            &lt;command1 /&gt;
            &lt;command2 /&gt;
            &lt;command3 /&gt;
            &lt;command4 /&gt;
            &lt;command5 /&gt;
          &lt;/command&gt;
          &lt;options&gt;
            &lt;loginmacro&gt;False&lt;/loginmacro&gt;
            &lt;postcommands&gt;False&lt;/postcommands&gt;
            &lt;endlinechar&gt;10&lt;/endlinechar&gt;
          &lt;/options&gt;
        &lt;/connection&gt;
END
;

#this is the wrapper
my $config= &lt;&lt;END
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!-- The following lines can be modified at your own risks.  --&gt;
&lt;configuration version="0.2.1.4" savepassword="True"&gt;
  &lt;root type="database" name="WSSS" expanded="True"&gt;
    &lt;container type="folder" name="CM" expanded="True"&gt;
      &lt;container type="folder" name="1-AD/M" expanded="True"&gt;
      &lt;/container&gt;
    &lt;/container&gt;
  &lt;/root&gt;
&lt;/configuration&gt;
END
;

#start an xml structure with the outer wrapper
my $tree=XML::TreeBuilder-&gt;new(); 
$tree-&gt;parse($config);

# find the insert location
my $container=$tree-&gt;look_down("_tag"=&gt;"container", "name"=&gt;"1-AD/M"); 
my $csv=Text::CSV-&gt;new(); 
open my $fh, "&lt;: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-&gt;getline($fh)){
	my $contree=XML::TreeBuilder-&gt;new();  #make an xml structure of the connection
	$contree-&gt;parse($connection);
	$container-&gt;push_content($contree);   #insert it into the wrapper
	$contree-&gt;attr('name',$row-&gt;[0]);     #set the name attribute
	$container-&gt;push_content("\n       ");  #make it a little prettier
	my $index=0;
	for my $tagname(@taglist){  		  #loop through the columns
		my $tag=$contree-&gt;look_down('_tag'=&gt; $tagname);
	    $tag-&gt;push_content($row-&gt;[$index++]);
	}  
	
}

print '&lt;?xml version="1.0" encoding="UTF-8"?&gt;'."\n";
print $tree-&gt;as_XML();
&lt;/code&gt;

And here's the output:
&lt;code&gt;$ perl puttyconfig.pl 
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;configuration savepassword="True" version="0.2.1.4"&gt;
  &lt;root expanded="True" name="WSSS" type="database"&gt;
    &lt;container expanded="True" name="CM" type="folder"&gt;
      &lt;container expanded="True" name="1-AD/M" type="folder"&gt;
      &lt;connection name="WSSSS" type="PuTTY"&gt;
          &lt;connection_info&gt;
            &lt;name&gt;WSSSS&lt;/name&gt;
            &lt;protocol&gt;SSH&lt;/protocol&gt;
            &lt;host&gt;103.243.543.233&lt;/host&gt;
            &lt;port&gt;22&lt;/port&gt;
            &lt;session&gt;Default Settings&lt;/session&gt;
            &lt;commandline&gt;erted&lt;/commandline&gt;
            &lt;description&gt;&lt;/description&gt;
          &lt;/connection_info&gt;
          &lt;login&gt;
            &lt;login&gt;&lt;/login&gt;
            &lt;password&gt;&lt;/password&gt;
            &lt;prompt&gt;&lt;/prompt&gt;
          &lt;/login&gt;
          &lt;timeout&gt;
            &lt;connectiontimeout&gt;1000&lt;/connectiontimeout&gt;
            &lt;logintimeout&gt;750&lt;/logintimeout&gt;
            &lt;passwordtimeout&gt;750&lt;/passwordtimeout&gt;
            &lt;commandtimeout&gt;750&lt;/commandtimeout&gt;
          &lt;/timeout&gt;
          &lt;command&gt;
            &lt;command1&gt;&lt;/command1&gt;
            &lt;command2&gt;&lt;/command2&gt;
            &lt;command3&gt;&lt;/command3&gt;
            &lt;command4&gt;&lt;/command4&gt;
            &lt;command5&gt;&lt;/command5&gt;
          &lt;/command&gt;
          &lt;options&gt;
            &lt;loginmacro&gt;False&lt;/loginmacro&gt;
            &lt;postcommands&gt;False&lt;/postcommands&gt;
            &lt;endlinechar&gt;10&lt;/endlinechar&gt;
          &lt;/options&gt;
        &lt;/connection&gt;
       &lt;connection name="AWSA" type="PuTTY"&gt;
          &lt;connection_info&gt;
            &lt;name&gt;AWSA&lt;/name&gt;
            &lt;protocol&gt;SSH&lt;/protocol&gt;
            &lt;host&gt;303.233.542.622&lt;/host&gt;
            &lt;port&gt;22&lt;/port&gt;
            &lt;session&gt;Default Settings&lt;/session&gt;
            &lt;commandline&gt;rrertd&lt;/commandline&gt;
            &lt;description&gt;&lt;/description&gt;
          &lt;/connection_info&gt;
          &lt;login&gt;
            &lt;login&gt;&lt;/login&gt;
            &lt;password&gt;&lt;/password&gt;
            &lt;prompt&gt;&lt;/prompt&gt;
          &lt;/login&gt;
          &lt;timeout&gt;
            &lt;connectiontimeout&gt;1000&lt;/connectiontimeout&gt;
            &lt;logintimeout&gt;750&lt;/logintimeout&gt;
            &lt;passwordtimeout&gt;750&lt;/passwordtimeout&gt;
            &lt;commandtimeout&gt;750&lt;/commandtimeout&gt;
          &lt;/timeout&gt;
          &lt;command&gt;
            &lt;command1&gt;&lt;/command1&gt;
            &lt;command2&gt;&lt;/command2&gt;
            &lt;command3&gt;&lt;/command3&gt;
            &lt;command4&gt;&lt;/command4&gt;
            &lt;command5&gt;&lt;/command5&gt;
          &lt;/command&gt;
          &lt;options&gt;
            &lt;loginmacro&gt;False&lt;/loginmacro&gt;
            &lt;postcommands&gt;False&lt;/postcommands&gt;
            &lt;endlinechar&gt;10&lt;/endlinechar&gt;
          &lt;/options&gt;
        &lt;/connection&gt;
       &lt;/container&gt;
    &lt;/container&gt;
  &lt;/root&gt;
&lt;/configuration&gt;

&lt;/code&gt;</field>
<field name="root_node">
1006069</field>
<field name="parent_node">
1006360</field>
</data>
</node>
