Reputation: 65
Need help in updating XML. I have gone through this link and it has been very helpful.
Perl code for Find and replace a tag value in XML
In continuation, I have created below code but still need more help. The tag value that I want to replace is 'numCoreThreads'.
When I give a tag value, it replaces the value and working fine.
Also, How can I add a new tag under a parent tag. Exp Add Tag -
<OptimizeThreshold>250</OptimizeThreshold> under
<ftOptimizeThreshold>1000</ftOptimizeThreshold>
My XML -->
<svr_config>
<port>34343</port>
<PortMapper>false</PortMapper>
<numCoreThreads>12</numCoreThreads>
<plugins>
<plugin>
<userDefined>
<ftOptimizeThreshold>1000</ftOptimizeThreshold>
</userDefined>
</plugin>
</plugins>
Current Code -->
#!C:\strawberry\perl
use strict;
use warnings;
use XML::Twig;
XML::Twig->new( twig_roots => { numCoreThreads => sub { $_->flush }, },
twig_handlers => { 'numCoreThreads[string()="12"]' => sub { $_->set_text( '5000'); } },
twig_print_outside_roots => 1,
)
->parsefile_inplace( 'config.xml');
Trying to make the code more dynamic like reading the input file and then updating the xml based on argument read from input file. I know...running the loop would print the whole file again...can we optimize that?
My Input file looks like this
numCoreThreads: 20
OptimizeThreshold: ftOptimizeThreshold: 250
Code I have made looks like this:
#!C:\strawberry\perl
use strict;
use warnings;
use XML::Twig;
open(IN1,"INPUT_FTS_XML_PRIMARY.txt");
while(my $r=<IN1>)
{
$r=~/(.*:)\s(.*)/;
my $c1=$1;
my $d1=$2;
my $f1=$3
my $twig = XML::Twig->new(
twig_handlers => {
'$c1' => sub { $_->set_text( 'd1' ) },
if (defined $f1)
{
'$d1' => sub {
my $e = XML::Twig::Elt->new( '$c1' => '$f1' );
$e->move( after => $_ );
},}
},
pretty_print => 'indented',
)->parsefile( shift )->print;
}
Upvotes: 3
Views: 917
Reputation: 36262
I would do all the work inside twig_handlers
:
#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;
my $twig = XML::Twig->new(
twig_handlers => {
'numCoreThreads' => sub { $_->set_text( '5000' ) },
'ftOptimizeThreshold' => sub {
my $e = XML::Twig::Elt->new( 'OptimizeThreshold' => '250' );
$e->move( after => $_ );
},
},
pretty_print => 'indented',
)->parsefile( shift )->print;
Run it like:
perl script.pl xmlfile
It yields:
<svr_config>
<port>34343</port>
<PortMapper>false</PortMapper>
<numCoreThreads>5000</numCoreThreads>
<plugins>
<plugin>
<userDefined>
<ftOptimizeThreshold>1000</ftOptimizeThreshold>
<OptimizeThreshold>250</OptimizeThreshold>
</userDefined>
</plugin>
</plugins>
</svr_config>
UPDATE: See comments.
Read each line of the file with arguments, split with colon and save fields in a data structure that fits your needs. Then simply replace literals with the content of these values.
die qq|Usage: perl $0 <arg-file> <xml-file>\n| unless @ARGV == 2;
open my $fh, '<', shift or die;
while ( <$fh> ) {
chomp;
my @f = split /\s*:\s*/;
## Save fields in a data structure.
}
Upvotes: 3