我有一个非常长的xml,我希望更新其中一个非常深嵌套的标记的属性值,所以不希望逐个节点地去。对于预期节点,结构也不同,如下所示: 输入XML是:
<Re>
<Co Class="Parameter" ID="CSCP001" Status="Available">
<FileSpec URL="c://mine/testfiles/wln/c.txt"/>
<CoOp Operation="Tag" SourceCS="RGB" SourceObjects="All">
<FileSpec Resource="SourceProfile" URL="c://mine/testfiles/wln/d.txt"/>
</CoOp>
</Co>
<Ru Class="Parameter" ID="IDR002" PartIDKeys="Run" Status="Available">
<Ru EndOfDocument="true" Pages="0" Run="1" RunTag="First">
<La>
<FileSpec URL="c://mine/testfiles/wln/e.txt"/>
</La>
</Ru>
</Ru>
</Re>
我希望输出xml为
<Re>
<Co Class="Parameter" ID="CSCP001" Status="Available">
<FileSpec URL="d://yours/wln/c.txt"/>
<CoOp Operation="Tag" SourceCS="RGB" SourceObjects="All">
<FileSpec Resource="SourceProfile" URL="d://yours/wln/d.txt"/>
</CoOp>
</Co>
<Ru Class="Parameter" ID="IDR002" PartIDKeys="Run" Status="Available">
<Ru EndOfDocument="true" Pages="0" Run="1" RunTag="First">
<La>
<FileSpec URL="d://yours/wln/e.txt"/>
</La>
</Ru>
</Ru>
</Re>
我尝试使用xml simple,xmllib但无法执行所需的操作。我是perl编程的新手。
use XML::LibXML qw( );
use XML::LibXML;
use Data::Dumper;
my $xml = "a.txt";
my $xpath_expression = 'FileSpec';
my $parser = XML::LibXML->new();
my $doc = $parser->parse_file($xml) or warn "Could not";
my $parser1 = XML::LibXML::Element->new($xml);
for my $FileSpec1 ($doc->getElementsByTagName('FileSpec'))
{
print $FileSpec1;
my $xpath = '$FileSpec1/@URL';
my ($attr) = $doc->findnodes($xpath);
$attr->setValue('dfdsa');
my ($URL1) = $FileSpec1->findvalue('@URL');
print $URL1;
}
我尝试使用$ node-&gt; setAttribute($ aname,$ avalue);但这是抛出异常。请指教。
答案 0 :(得分:4)
您的代码太复杂了。你不需要解析器,没有元素,只需找到网址并进行更改:
#!/usr/bin/perl
use warnings;
use strict;
use XML::LibXML;
my $xml = 'XML::LibXML'->load_xml(location => 'a.xml') ;
for my $url ($xml->findnodes('//FileSpec/@URL')) {
my $value = $url->getValue;
$value =~ s{c://mine/testfiles}{d://yours};
$url->setValue($value);
}
$xml->toFile('new.xml');
答案 1 :(得分:1)
您可以尝试使用XML::Twig
模块。它具有twig_handlers
选项,用于选择所需的标记并触发处理程序。默认变量$_
包含元素,其方法set_att()
可让您轻松更改其值:
#!/usr/bin/env perl
use warnings;
use strict;
use XML::Twig;
my $new_url = q{d://yours/wln/d.txt};
my $twig = XML::Twig->new(
twig_handlers => {
'FileSpec' => sub { $_->set_att( 'URL', $new_url ) }
},
pretty_print => 'indented',
)->parsefile( shift )->print();
像以下一样运行:
perl script.pl xmlfile
产量:
<Re>
<Co Class="Parameter" ID="CSCP001" Status="Available">
<FileSpec URL="d://yours/wln/d.txt"/>
<CoOp Operation="Tag" SourceCS="RGB" SourceObjects="All">
<FileSpec Resource="SourceProfile" URL="d://yours/wln/d.txt"/>
</CoOp>
</Co>
<Ru Class="Parameter" ID="IDR002" PartIDKeys="Run" Status="Available">
<Ru EndOfDocument="true" Pages="0" Run="1" RunTag="First">
<La>
<FileSpec URL="d://yours/wln/d.txt"/>
</La>
</Ru>
</Ru>
</Re>
编辑:Mirod's版本在使用twig_roots()
进行更有效解析的评论中指出:
#!/usr/bin/env perl
use warnings;
use strict;
use XML::Twig;
my $new_url = q{d://yours/wln/d.txt};
my $twig = XML::Twig->new(
twig_roots => {
'FileSpec' => sub { $_->set_att( 'URL', $new_url ); $_->flush }
},
twig_print_outside_roots => 1,
pretty_print => 'indented',
)->parsefile( shift );