【问题标题】:Replace values for multiple XML files in a folder using perl使用 perl 替换文件夹中多个 XML 文件的值
【发布时间】:2013-05-09 07:03:57
【问题描述】:

我在一个文件夹“c:\srini\perl\in\”中有多个 XML 文件......所有这些文件的结构都是相同的......我需要在每个 XML 中搜索两个标签,如果那样的话TAG 值中有“@@@”...它必须替换为“&”...它必须检查两个标签值 SHORT_DESC 和 XXX_NAME ...如果任何 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 $!;

【问题讨论】:

  • 还有一种方法可以编辑同一个文件并替换值..我不希望使用 _out 扩展名创建新文件...

标签: xml perl replace


【解决方案1】:

您意识到您的输出将不是有效的 XML,对吧? & 需要在 XML 中转义。希望这只是一个例子,而不是真正的价值。

也就是说,我想使用“XML 方式”™,例如使用 XML::Twig,这很简单:

#!/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 &lt;SHORT_DESC&gt;ABC COMPY &amp;amp; LTD&lt;/SHORT_DESC&gt;)。如果您确实需要 & 不被转义,则 sub 中的行应该是 $elt-&gt;subs_text( qr/@@@/, '&amp;')-&gt;set_asis( 1)-&gt;print;,对 set_asis 的调用可以防止元素的文本被转义。

请确保您的原始 XML 格式正确,否则将不会被处理(但您不会丢失数据)。

【讨论】:

  • 感谢更新和代码 mirod .. 我用实际的 XMl 运行了代码,“&”值被替换为“&” ...有没有办法可以替换“&”而不是“&”
【解决方案2】:

opendir/readdir/closedir 函数让您可以遍历目录的文件系统对象:

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);

【讨论】:

  • 嗨...谢谢代码...但我在执行代码时遇到以下错误..在replace2.pl第2行的opendir没有足够的参数,靠近“$dir or " 在 replace2.pl 第 6 行的最后 $ 应该是 \$ 或 $name,在 replace2.pl 第 6 行的字符串语法错误之内,靠近 "=~ "\*.xml$"" 在 replace2.pl 第 20 行的语法错误,靠近"}" replace2.pl 的执行由于编译错误而中止。
猜你喜欢
  • 2014-06-01
  • 1970-01-01
  • 2022-01-25
  • 1970-01-01
  • 2015-11-07
  • 2019-10-27
  • 2021-06-01
  • 2021-01-28
  • 1970-01-01
相关资源
最近更新 更多