我想根据用户的输入文件执行添加/删除功能。
我有两个文件。一个是用户的输入文件,另一个是原始xml文件。 首先是检查用户的请求ID是否在原始配置中存在。如果存在,它将执行删除功能,如果在原始配置文件中没有ID退出,它将执行添加功能。基于用户的输入文件请求。我开始学习perl脚本。请帮助建议如何添加/删除功能到原始配置文件。非常感谢:)
下面是我用户的输入文件
add:L83A:55FIP:11:18: #addfunction:DesignID:ProcessID:registerIDs
del:L83A:FRP:149:155:194: #deletefunction:DesignID:ProcessID:registerIDs
这是我原始的xml配置文件
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Sigma>
<Run>
<DESIGN_ID>L83A</DESIGN_ID>
<PROCESS_ID>55FIP</PROCESS_ID>
<RegisterList>
<Register>70</Register>
<Register>155</Register>
</RegisterList>
</Run>
<Run>
<DESIGN_ID>L83A</DESIGN_ID>
<PROCESS_ID>FRP</PROCESS_ID>
<RegisterList>
<Register>141</Register>
<Register>149</Register>
<Register>151</Register>
<Register>152</Register>
<Register>155</Register>
<Register>194</Register>
</RegisterList>
</Run>
</Sigma>
因此,应通过编写xml文件来显示结果
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Sigma>
<Run>
<DESIGN_ID>L83A</DESIGN_ID>
<PROCESS_ID>55FIP</PROCESS_ID>
<RegisterList>
<Register>70</Register>
<Register>155</Register>
<Register>11</Register>
<Register>18</Register>
</RegisterList>
</Run>
<Run>
<DESIGN_ID>L83A</DESIGN_ID>
<PROCESS_ID>FRP</PROCESS_ID>
<RegisterList>
<Register>141</Register>
<Register>151</Register>
<Register>152</Register>
</RegisterList>
</Run>
</Sigma>
但是我的代码仅替换11和18而不是添加。并且也无法执行删除功能:(
这是我的代码:
use strict;
use warnings;
use XML::Simple;
use Data::Dumper;
use feature 'say';
my $filename = 'new.txt';
my $data;
my $run;
open(FILE, '<', $filename) or die $!;
foreach $run(@{XMLin('sigma_loader.xml')->{Run}}) # see how it looks
{
$data->{$run->{DESIGN_ID}}->{$run->{PROCESS_ID}} =
{map { $_ => 1 } @{$run->{RegisterList}->{Register}}};
}
while (<FILE>)
{ my $line = $_;
chomp $line ;
my ($action,$design_id, $process_id, @register_ids) = split /:/, $line; #split the line with add:design_ID:process_ID:register_ID
if(exists $data->{$design_id})
{
if (exists $data->{$design_id}->{$process_id})
{
my $register_id;
foreach $register_id (@register_ids) {
if (exists $data->{$design_id}->{$process_id}->{$register_id}) {
say " $design_id: $register_id - existing register ID";
}
else {
say " $design_id : $register_id - no existing register ID";
}
if($action eq 'add')
{
$data->{$design_id}->{$process_id}= {$register_id , '1'};
print Dumper($data);
}
if($action eq 'del')
{
my $xml = XMLin('sigma_loader.xml', ForceArray => 1, KeepRoot => 1);
delete $xml->{DESIGN_ID}[0]{PROCESS_ID}[0]{RegisterList}[0]{Register}{$register_id};
print XMLout($xml, KeepRoot => 1)
}
}
}
else{
say "$design_id: doesn't have $process_id";
}
}
else
{
say "$design_id does't exist in data";
}
}
答案 0 :(得分:1)
不要使用XML::Simple
,使用适当的XML模块,例如XML::LibXML
。这将产生您的预期输出(空白可能不大):
#!/usr/bin/env perl
use warnings;
use strict;
use XML::LibXML;
my $xmlfile = 'sigma_loader.xml';
my $commandfile = 'commands.txt';
my $DEBUG = 1;
my $doc = XML::LibXML->load_xml(location => $xmlfile);
open my $fh, '<', $commandfile or die "$commandfile: $!";
while ( my $line = <$fh> ) {
chomp($line);
my ($action,$design_id,$proc_id,@register_ids) = split /:/, $line;
my @runs = $doc->findnodes("/Sigma/Run[DESIGN_ID='$design_id'"
." and PROCESS_ID='$proc_id']");
print STDERR "Found ".@runs." Run nodes matching DESIGN_ID="
."$design_id PROCESS_ID=$proc_id\n" if $DEBUG;
for my $run (@runs) {
my ($reglist) = $run->findnodes('./RegisterList')
or die "Failed to find RegisterList";
my @regs = $reglist->findnodes('./Register['
.join(' or ', map {"text()='$_'"} @register_ids).']');
print STDERR "Found ".@regs." Register nodes for IDs "
.join(',',@register_ids)."\n" if $DEBUG;
if ($action eq 'add') {
my %regs = map { $_->textContent => $_ } @regs;
for my $regid (@register_ids) {
next if exists $regs{$regid};
my $reg = $doc->createElement('Register');
$reg->appendText($regid);
$reglist->appendChild($reg);
print STDERR "Added Register $regid\n" if $DEBUG;
}
}
elsif ($action eq 'del') {
for my $reg (@regs) {
print STDERR "Removing Register "
.$reg->textContent."\n" if $DEBUG;
$reglist->removeChild($reg);
}
}
else { die "Unknown action '$action'" }
}
}
print $doc->toString(1);
请注意,这有一些假设,例如不验证命令文件,假设$design_id
和$proc_id
之类的值不会破坏XPath引用,假设每个RegisterList
Run
,或者假设在每个RegisterList
中,Register
是唯一的。您可能需要根据输入文件的规范来调整其中的一些内容。