0

I have a xml file contain data's like:

 <get>9090</get><br>
 <setId>setIdHere</set>
 <mainId>121</mainId>

As I'm not using any external lib/packages, however I'm need to do some changes using I/O.

I need to change the string setIdHere with something. Please find the perl code below:

my $filename="file1.xml";
my $idVal=3232;
open(my $fh , '>>' ,$fileName);
select $fh or die $!;
s/setIdHere/$idVal;
print;
select STDOUT;
close($fh);

The above code is appending the value in the end, but I want to replace it with the string setIdHere.

I'm new to perl not sure what's wrong with the above code.

Thanks in advance.

ssr1012
  • 2,573
  • 1
  • 18
  • 30
  • Your code does not compile. It also never reads the file. Could you copy and past in the real code? – Schwern Dec 16 '16 at 06:05

2 Answers2

2

First off, your code is using some unusually outdated techniques. select $fh has a global effect and is best avoided.

In general to edit a file you need to open it for reading, read it in, alter it, and write it back out again. To avoid pulling the whole file into memory, the file can be very big, you generally do this line by line.

You can't write to the same file you're reading from (well, you can, but it makes a mess), so instead you write to a temp file and then when you're done rename to be the original.

# This forces you to declare all variables protecting against typos
use strict;
# This lets you know when you've done something you probably shouldn't.
use warnings;
# This will error if file operations failed, no more "or die $!"
use autodie;

my $file = "file1.xml";
my $tmp  = $file.".new";  # file1.xml.new

open my $in,  "<", $file;  # open the XML file for reading
open my $out, ">", $tmp;   # open a temp file for writing

# Read the file line by line
while(my $line = <$in>) {
    # Change the line.
    $line =~ s{this}{that}g;

    # Write it to the temp file.
    print $out $line;
}

# If you don't do this, it might not have finished writing.
close $out;
close $in;

# Overwrite the old file with the new one.
rename $temp, $file;

HOWEVER you're editing XML. XML is structured and you should not try to read and edit it with regexes. You instead need to parse it with an XML library like XML::LibXML or XML::Twig.

You say you can't use any external library, but I bet you can, it's just a matter of figuring out how. You'll have a much easier time of it if you do. Generally the reason is that you don't have admin privileges. The simplest solution is to install perlbrew and install your own copy of Perl that you can manage. Perlbrew makes this easy.

Schwern
  • 153,029
  • 25
  • 195
  • 336
  • Please don't recommend [`XML::Simple`](http://stackoverflow.com/questions/33267765/why-is-xmlsimple-discouraged) - even the documentation for it suggests using something else. `XML::LibXML` and `XML::Twig` are both far better choices. – Sobrique Dec 16 '16 at 09:03
  • @Sobrique Okie doke. – Schwern Dec 16 '16 at 10:54
1

Please, never ever use regular expressions to parse XML. XML is contextual, and regular expressions are not. Therefore it's only ever going to be a dirty hack.

I would recommend XML::Twig if you need to modify an XML file. It supports xpath, which is like regular expressions, but inherently handles the context problem.

XML::Twig also does 'parsefile_inplace' for in place editing of your file:

#!/usr/bin/env perl

use strict;
use warnings;

use XML::Twig;

sub modify_setId {
    my ( $twig, $setId ) = @_;
    $setId -> set_text('3232');
    $twig -> flush; 
}

my $twig = XML::Twig -> new ( twig_handlers => { 'setId' => \&modify_setId } );
$twig -> set_pretty_print('indented'); 
$twig -> parsefile_inplace('test.xml');
Community
  • 1
  • 1
Sobrique
  • 52,974
  • 7
  • 60
  • 101