Question

I have a large xml of which I want to replace one of the attributes of node. I have a code which replaces the value of the attribute for the given node but it does not write to disk. I am not sure how should I make those changes propagated to disk?

For e.g: example.1.xml

<chairman name="abc" >
<vicechairman name="def">
<employee name="ghi" salary="123" designation="xyz"/>
</vicechairman>
</chairman>

In above example, I would like to change the value of employee nodes with "salary="123"" attribute to "salary="456"" such that above xml changes to:

<chairman name="abc" >
<vicechairman name="def">
<employee name="ghi" salary="456" designation="xyz"/>
</vicechairman>
</chairman>

I have following piece of code which after getting to node of "employee" changes the Attribute value to "salary=456", but does not write to disk:

foreach my $anode (@attributes){
    my $attr = $anode->nodeName;
    if($attr eq "salary"){
        $anode->setValue( "456" );
    }
}

Any help will be Appreciated. Thanks

Was it helpful?

Solution

If using XML::LibXML, explicitly write the revised contents to disk:

# save
open my $out, '>', 'out.xml';
binmode $out; # as above
$doc->toFH($out);
# or
print {$out} $doc->toString();

OTHER TIPS

With XML::Twig:

#!/usr/bin/perl

use strict;
use warnings;

use XML::Twig;

my $old_sal="123";
my $new_sal="456";

XML::Twig->new( twig_roots => { qq{employee[\@salary="$old_sal"]} 
                                  => sub { $_->set_att( salary => $new_sal); $_->flush; } 
                              },
                twig_print_outside_roots => 1,
              )
         ->parsefile_inplace( 'emp.xml');

This updates the file inplace.If you don't want to update inplace, use ->print_to_file( 'out.xml')

This will work without using much memory, as only the nodes that trigger the handler are loaded in memory (and removed once used, so you only have a single one in memory at any given time).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top