Arjun Bhatta
Arjun Bhatta

Reputation: 23

How do I edit the contents of an XML file in perl?

I am new to perl, so please excuse my naivety.

I have a few thousand XML files and their corresponding older versions, for each in each of which I need to read one value (Movie -> Weight) from the old XML file and update it to the new XML file, ideally keeping the same filename.

Files, partly look like this.

# Old XML file
<?xml version="1.0" encoding="UTF-16"?>

-<Movie MagnificationCorrection="1, 1, 0" Weight="1" Bfactor="0" MaskPercentage="1.5895931142410015649452269200" MeanFrameMovement="0.8939736" CTFResolutionEstimate="3.1" UnselectManual="null" UnselectFilter="False">
</Movie>
# new XML file
<?xml version="1.0" encoding="UTF-16"?>

-<Movie MagnificationCorrection="1, 1, 0" Weight="3" Bfactor="0" MaskPercentage="1.5895931142410015649452269200" MeanFrameMovement="0.3284904" TFResolutionEstimate="3.1" UnselectManual="null" UnselectFilter="False">
</Movie>

My approach was rather crude: I parsed the old file using XML::LibXML and extacted the old value,

use warnings;
use XML::LibXML;

my $olddom = XML::LibXML -> load_xml(location => "oldfile.xml");

my $oldWeight = $olddom -> findnodes('//movie/@Weight');

and then tried opening the new XML file in write mode and old file in read mode so that I would copy and print every row from the old file to the new unless the row happens to have the keyword " Weight=", in which case it would edit the row to contain the old weight value and then print the row in the new file.

#Apologies for how crude the code looks.

open (my $oldfh,"<oldfile.xml") or die "Not found\n";
open (my $newfh, ">newfile.xml") or die "Error\n";

my $matchstring = ' Weight=';

while (my $row = <$oldfh>){
    my $match = 0;
    my @row_comp = split(/"/,$row);
    foreach my $row_comp(@row_comp){
        if ($row_comp eq $matchstring){
            my $match = 1;
        }
    }

    if $match == 1{
        my $newrow = @row_comp[0];
        foreach (1..16){
            if $_ == 2{
                $newrow = $newrow . "\"" . $oldWeight;
            }else{
                $newrow = $newrow . "\"". @row_comp[$_]);
            }
        }
    }else{
        print $newfh $row;
    {
    }       
}

However, ($row_comp eq $matchstring) never gives me "True" value even though I checked the values to be equal by printing them. Could it be because of encoding? If so, how can I fix it? I am sure there are more elegant ways to achieve what I am trying; I figured this would be a quick and dirty way to solve my problem (evidently not). I would greatly appreciate any suggestions.

Upvotes: 2

Views: 261

Answers (1)

choroba
choroba

Reputation: 241858

I'd use XML::LibXML to change the value, too.

#!/usr/bin/perl
use warnings;
use strict;

use XML::LibXML;

my $olddom = 'XML::LibXML'->load_xml(location => 'old.xml');
my $oldweight = ($olddom->findnodes('//Movie/@Weight'))[0]->value;

my $newdom = 'XML::LibXML'->load_xml(location => 'new.xml');
my $newweight = ($newdom->findnodes('//Movie/@Weight'))[0];
$newweight->setValue($oldweight);
$newdom->toFile('new2.xml');

Upvotes: 4

Related Questions