ilottl has asked for the wisdom of the Perl Monks concerning the following question:

Well it has been a very lonnngggg time since I used Perl and after a few days of whacking my keyboard and I have come to the monks for advice. I have numerous XML files in multiple subdiretories, for example. All I want to do is simple replace of information within the file, eg <label> with <label denominator=no> But I just cannot do it. This is the code I have so far...
use strict; use File::Find; use HTML::TokeParser; my $bak_ext = '.bak'; my $root_dir = 'C:/Temp/Chris'; find(\&wanted, $root_dir); sub wanted { # if the extension fits... if ( /\.xml?/i ) { print "Processing $_\n"; my $new = $_; my $bak = $_ . $bak_ext; rename $_, $bak or die "Cannot rename $_ to $bak: $!"; open NEW, "> $new" or die "Cannot open $new for writing: $!"; my $p = HTML::TokeParser->new( $bak ); while ( my $token = $p->get_token ) { my $text_index = $token->[0] eq 'T' ? 1 : -1; $token->[ $text_index ] =~ s/<label>CA 3<\/<label>\/Scrap/i; print NEW $token; } close NEW; } else { print "Skipping $_\n"; } }
Where am I going wrong! Please help.
  • Comment on Performing a search and replace in XML across multiple directories
  • Download Code

Replies are listed 'Best First'.
Re: Performing a search and replace in XML across multiple directories
by samtregar (Abbot) on May 16, 2006 at 22:08 UTC
    Maybe if you told us what wasn't working we could help you. I'm suspicious of how you're using HTML::TokeParser, but I'm not terribly familiar with the module.

    -sam

      Oh sorry, the script ony works if I ask to replace text only. However it will not pickup contents such as greater and less than signs, hyphenation etc. It only seems to be working on text. I am not concerned with using HTML:Tokkeparser or not.
        OK, I have updated the script to this.. It renames the file corrctly but I get no output in the renamed file.
        use File::Find; use strict; my $bak_ext = '.bak'; my $root_dir = 'C:/Temp/Chris/'; find(\&fix, $root_dir); sub fix { # if the extension fits... if ( /\.xml?/i ) { print "Processing $_\n"; my $new = $_; my $bak = $_ . $bak_ext; rename $_, $bak or die "Cannot rename $_ to $bak: $!"; open OUTPUT, "> $new" or die "Cannot open $new for writing: $! +"; while ( <OUTPUT> ) { Print Go Go Go; my $TheLine = $_; s/<label>([^<]*<\/label>)/<label denominator=no auto.number=no>$1/i; print OUTPUT; } } close OUTPUT; }
      Hi Sam, I updated the code (see below). I think what is happening is that it is not opening the file but is only processing the name of the file. How do I make it open the content of the file to do the substitution?
      use File::Find; use strict; my $bak_ext = '.bak'; my $root_dir = 'C:/Temp/Chris/Bills/'; find(\&wanted, $root_dir); sub wanted { # if the extension fits... if ( /\.xml?/i ) { print "Processing $_\n"; my $new = $_; my $bak = $_ . $bak_ext; rename $_, $bak or die "Cannot rename $_ to $bak: $!"; open OUTPUT, "> $new" or die "Cannot open $new for writing: $! +"; while ( <OUTPUT> ) { my $TheLine = $_; s/Draft/Scrap/i; s/<label>([^<]*<\/label>)/<label denominator=no auto.number=no>$1/i; print OUTPUT; } close OUTPUT; } else { print "Skipping $_\n"; } }
        Thanks Grandfather, that is what I was trying to do.