3

下面是我将使用的 XML:

<a>

<id>ABC</id>

<class />

<gender />

</a>

我想编写一个搜索标记“id”并将值“ABC”替换为“DEF”的 Perl 代码。

然而,上述 XML 的嵌套可以改变。因此,我想制作一个通用代码来搜索标签“id”,而与它的确切位置无关。

到现在为止,我能够获得可以替换 ABC 中的值的逻辑,但这会使我的代码静态标记“id”的位置。

#!usr/bin/perl
use warnings;
use XML::Simple;
use Spreadsheet::ParseExcel;
use Data::Dumper;
my $FileName = 'sample.xls';
my $xml_file = 'hello.xml';
$par=$ARGV[0];
my $xml = XMLin($xml_file,
    KeepRoot=>1,
    ForceArray=>1,);
$xml->{a}->[0]->{id}='DEF';
XMLout(
    $xml,
    KeepRoot =>1 ,
    NoAttr =>1,
    OutputFile => $xml_file,
        );
    }
4

3 回答 3

7

XPath 能够找到节点而不需要知道树中的位置。

use strictures;
use XML::LibXML qw();
my $dom = XML::LibXML->load_xml(string => <<'XML');
<a>
<id>ABC</id>
<class />
<gender />
</a>
XML

for my $id ($dom->findnodes('//id[string()="ABC"]')) {
    $id->removeChildNodes;
    $id->appendText('DEF');
}

print $dom->toString
于 2012-07-14T09:25:33.090 回答
4

一个简单的 XML::Twig 解决方案是:

#!/usr/bin/perl

use strict;
use warnings;

use XML::Twig;

my $FILE= 'id.xml';

XML::Twig->new( twig_handlers => { 'id[string()="ABC"]' => sub { $_->set_text( 'DEF'); } },
                keep_spaces => 1,
              )
          ->parsefile( $FILE)
          ->print_to_file( $FILE);

只是为了好玩:一个高效的 XML::Twig 解决方案有点复杂,主要是因为你不能string()使用twig_roots. 尽管如此,它仍然非常紧凑,并且它永远不会将整个文件加载到内存中。

#!/usr/bin/perl

use strict;
use warnings;

use XML::Twig;

XML::Twig->new( twig_roots =>    { id => sub { $_->flush }, },
                twig_handlers => { 'id[string()="ABC"]' => sub { $_->set_text( 'DEF'); } },
                twig_print_outside_roots => 1,
              )
          ->parsefile_inplace( 'id.xml');
于 2012-07-16T10:33:51.043 回答
0

perl -i.bak -pe 's/abc/def/g' myfile.xml

你会得到一个新文件 myfile.xml.bak

于 2016-03-28T10:25:36.447 回答