santosh
santosh

Reputation: 501

Unable to add new tag using XML::Twig module in perl

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.xml i can't see the changes in it. Anyone please help!

Upvotes: 0

Views: 107

Answers (2)

Sobrique
Sobrique

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

Dave Cross
Dave Cross

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

Related Questions