1

フォルダー「c:\srini\perl\in\」に複数の XML ファイルがあります...これらすべてのファイルの構造は同じです...各 XML で 2 つのタグを検索する必要があり、そのタグ値がその中の "@@@" ... "&" に置き換える必要があります ... SHORT_DESC と XXX_NAME の 2 つのタグ値をチェックする必要があります ... TAG 値のいずれかに "@@@" が含まれている場合..「&」に置き換える必要があります..以下はXMLファイルです....

<TOPHEADER>
<HEADER>
<NAME>ABC LTD</NAME>
<SHORT_DESC>ABC COMPY @@@ LTD</SHORT_DESC> 
<XXX_NAME>ABC COMPANY FOR XXX AND YYY </XXX_NAME> 
</HEADER>
<HEADER>
<NAME>XYZ LTD</NAME>
<SHORT_DESC>XYZ COMPY @@@ LTD</SHORT_DESC> 
<XXX_NAME>XYZ COMPANY FOR @@@</XXX_NAME> 
</HEADER>
<HEADER>
<NAME>DEF LTD</NAME>
<SHORT_DESC>DEF COMPY AND LTD</SHORT_DESC> 
<XXX_NAME>DEF COMPANY FOR @@@</XXX_NAME> 
</HEADER>
</TOPHEADER>

以下のコードを使用して、単一のファイルのタグ値を置き換えています..しかし、複数のファイルを処理するためのより良い方法があるかどうか知りたい....

open (my $input_file, '<', 'c:\srini\perl\in\test1.xml') or die "unable to open $input_file $!\n";
open (my $output_file, '>', 'c:\srini\perl\in\test1_out.xml') or die "unable to open $output_file $!\n";

my $input;
{
local $/;               #Set record separator to undefined.
$input = <$input_file>; #This allows the whole input file to be read at once.
}
$input =~ s/@@@/&/g;

print {$output_file} $input;

close $input_file or die $!;
close $output_file or die $!;
4

2 に答える 2

2

出力が有効な XML ではないことに気付きましたよね? & は XML でエスケープする必要があります。うまくいけば、それは単なる例であり、実際の値ではありません.

そうは言っても、たとえば XML::Twig を使用して、この「XML の方法」™ を実行したいのですが、それは非常に簡単です。

#!/usr/bin/perl

use strict;
use warnings;

use XML::Twig;

my $dir= shift @ARGV or die "usege: $0 <dir>\n";

foreach my $file ( glob( "$dir/*.xml"))
  { XML::Twig->new( twig_roots => { SHORT_DESC => \&replace, # only those elements will be checked
                                    XXX_NAME   => \&replace,
                                  },
                    twig_print_outside_roots => 1,           # the rest will be output as-is
                    keep_spaces => 1,
                  )
             ->parsefile_inplace( $file);                    # the original file will be updated
  }

exit;

sub replace
  { my( $t, $elt)= @_;
    $elt->subs_text( qr/@@@/, '&')->print;
  }

出力は整形式の XML (つまりit will look like <SHORT_DESC>ABC COMPY &amp; LTD</SHORT_DESC>) になります。& をエスケープしないようにする必要がある場合は、sub の行を にする必要があります$elt->subs_text( qr/@@@/, '&')->set_asis( 1)->print;。 を呼び出すとset_asis、要素のテキストがエスケープされなくなります。

ただし、元の XML が適切な形式であることを確認してください。そうしないと、処理されません (データが失われることはありません)。

于 2013-05-09T08:13:04.930 に答える
0

opendir//関数を使用するreaddirclosedir、ディレクトリのファイル システム オブジェクトを反復処理できます。

my $dir = ***dir goes here***;
my $d = opendir();
map {
    if (
        -f "$dir/$_"
        && ($_ =~ "\.xml$")
    ) {
        open (my $input_file, '<', ) or die "unable to open $input_file $!\n";

        my $input;
        {
            local $/;               #Set record separator to undefined.
            $input = <$input_file>; #This allows the whole input file to be read at once.
        }
        close $input_file;

        $input =~ s/@@@/&/g;

        open (my $output_file, '>', "$dir/$_") or die "unable to open $output_file $!\n";
        print {$output_file} $input;

        close $output_file or die $!;
    }
} readdir($d);
closedir($d);
于 2013-05-09T07:33:22.133 に答える