我不是一个开发人员,而是一个网络安全人员。如果元素尚不存在,我需要插入一个标记和值。
这是我的XML文件的片段
<NessusClientData_V2>
<Policy>
...
<Report>
...
<ReportHost name="1.2.3.4">
...
<HostProperties>
...
<tag name="HOST_END">Thu Sep 17 17:23:19 2015</tag>
<tag name="system-type">general-purpose</tag>
<tag name="operating-system">MS WIN</tag>
<tag name="ssh-auth-meth">password</tag>
<tag name="ssh-login-used">backup</tag>
<tag name="local-checks-proto">ssh</tag>
<tag name="host-ip">1.2.3.4</tag>
<tag name="HOST_START">Thu Sep 17 17:00:14 2015</tag>
</HostProperties>
...
我需要检查每个ReportHost
元素并创建一个
<tag name="mac-address">
如果它还没有。
我的输出需要包含所有原始信息,但只需要添加到。
答案 0 :(得分:0)
您可以使用XML::Twig执行此操作。以下代码迭代所有HostProperties
个节点并检查它们是否存在tag
name mac-address
,如果不存在,则插入一个。
use strict;
use warnings;
use XML::Twig;
# at most one div will be loaded in memory
my $twig = XML::Twig->new(
twig_handlers => {
'//ReportHost/HostProperties' => sub {
my $seen = 0;
foreach my $elem ( $_->children('tag') ) {
if ( $elem->atts->{name} eq 'mac-address' ) {
$seen++;
last;
}
}
$_->insert_new_elt(
'last_child',
'tag' => { name => 'mac-address' },
'barfoo'
) unless $seen;
}
},
pretty_print => 'indented',
);
$twig->parse( \*DATA );
$twig->flush;
__DATA__
<NessusClientData_V2>
<Policy>
<Report>
<ReportHost name="1.2.3.4">
<HostProperties>
<tag name="HOST_END">Thu Sep 17 17:23:19 2015</tag>
<tag name="system-type">general-purpose</tag>
<tag name="operating-system">MS WIN</tag>
<tag name="ssh-auth-meth">password</tag>
<tag name="ssh-login-used">backup</tag>
<tag name="local-checks-proto">ssh</tag>
<tag name="host-ip">1.2.3.4</tag>
<tag name="HOST_START">Thu Sep 17 17:00:14 2015</tag>
</HostProperties>
</ReportHost>
<ReportHost name="127.0.0.1">
<HostProperties>
<tag name="HOST_END">Thu Sep 17 17:23:19 2015</tag>
<tag name="system-type">general-purpose</tag>
<tag name="operating-system">MS WIN</tag>
<tag name="ssh-auth-meth">password</tag>
<tag name="ssh-login-used">backup</tag>
<tag name="local-checks-proto">ssh</tag>
<tag name="host-ip">127.0.0.1</tag>
<tag name="HOST_START">Thu Sep 17 17:00:14 2015</tag>
<tag name="mac-address">foobar</tag>
</HostProperties>
</ReportHost>
</Report>
</Policy>
</NessusClientData_V2>
您必须将->parse(\*DATA)
替换为->parse_file
,并可能添加一些随机的mac地址。
答案 1 :(得分:0)
好吧,我在perlmonks上回答,并且通过更多的XML示例,我将回收答案。对于这个技巧,我使用xpath
来查询XML,而不是走树。这背后的原因是因为xpath
允许您在单个语句中查询元素,属性和属性内容。
#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;
my $twig = XML::Twig->parsefile( 'your_file.xml' );
#search for "HostProperties" nodes within the tree. You can
#be more specific about this if you need to.
foreach my $HP ( $twig->get_xpath('//HostProperties') ) {
#check if it has a "tag" element with a "mac-address" "name" attribute.
if ( not $HP->get_xpath('./tag[@name="mac-address"]') ) {
#insert a new element at the end of the entry.
$HP->insert_new_elt( 'last_child',
'tag', { 'name' => 'mac-address' },
"DE:AD:BE:EF:F0:FF" );
}
}
#note - pretty printing helps reading, but might
#cause some problems with certain XML constructs. Shouldn't in your specific example though.
$twig->set_pretty_print("indented_a");
$twig->print;
#to save it to a file:
open ( my $output, '>', 'processed.xml' ) or die $!;
print {$output} $twig -> sprint;
close ( $output );