Reputation: 501
i am trying to check whether the tag is present/not and adding the same if its not available. In this case i am trying to add new tag :<testProd>true</testProd>
inside <characteristics>
tag.
My xml:-
<?xml version="1.0"?>
<test testProp="false">
<Env>
<log>XM</log>
<uvmversion>1.2</uvmversion>
</Env>
<classes>
<class instances="1" name="total"/>
</classes>
<characteristics>
<pctest>true</pctest>
</characteristics>
</test>
Script:-
use strict;
use warnings;
use XML::Twig;
my $twig = XML::Twig->new(
pretty_print => 'indented',
twig_handlers => {
testProd => \&Check_tag,
characteristics => sub {
$_->insert_new_elt( last_child => 'supportsMVV' )->set_text('true'); 'true' );
},
},
);
$twig->parsefile('applying.xml');
$twig->print;
sub Check_tag{
my $item = $_->tag;
if (defined $item) {
print "'testProd' tag is already defined in given xml file.\n ";
exit;
}
}
Not sure whats wrong with my script.I am able to print the output of xml using '$twig->print;'
statement which has required changes that i am expecting. But in my file applying.xm
l i can't see the changes in it. Anyone please help!
Upvotes: 0
Views: 107
Reputation: 53498
twig_handlers
is IMO one of the features of XML::Twig
that's both amazing, but also unduely confusing.
I'd suggest not using it, unless you need to incrementally parse or pre-process your XML.
So I'd tackle your problem more like this:
#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;
my $xml = XML::Twig -> new ->parsefile('applying.xml');
#get_xpath finds all characteristics nodes in the tree, and allows you to
#iterate. "//" means any depth.
foreach my $element ( $xml -> get_xpath('//characteristics') ) {
$element -> insert_new_elt ( 'last_child' => 'supportsMVV') -> set_text('true');
}
$xml -> set_pretty_print('indented');
$xml -> print;
It's using get_xpath
to walk the XML tree, and find all the characteristics
nodes, before altering each of them. I feel this is both cleaner, and less confusing.
You can also use xpath
to test for conditions in your XML as XPath
is a fairly comprehensive way of interpreting an XML document. Or just do it 'perlishly' within the iterated element.
Anyway, the reason you're not seeing your thing being changed, is you're not actually writing out the changes - $xml -> print;
only changes the file if you're doing parsefile_inplace
.
But I'd suggest you don't want to do that, either - just save a copy of your output.
E.g.:
open ( my $output, ">", "applying.new.xml" ) or die $!;
$xml -> print ( $output );
Upvotes: 3
Reputation: 69314
You are reading data from a file, making changes to the in-memory copy of the data and then not writing the changed data back to the original file.
At the end of your code, you need to add something like:
open my $out_fh, '>', 'new_applying.xml' or die $!;
print $out_fh $twig->print;
Upvotes: 0