首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用Perl向XML文件中有条件地添加标签

使用Perl向XML文件中有条件地添加标签
EN

Stack Overflow用户
提问于 2015-10-30 06:45:50
回答 2查看 216关注 0票数 0

我不是一个开发人员,而是一个网络安全人员。如果元素尚不存在,则需要为其插入标记和值。

下面是我的XML文件的一个片段

代码语言:javascript
运行
复制
<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元素并创建一个

代码语言:javascript
运行
复制
<tag name="mac-address">

如果它还没有一个的话。

我的输出需要包含所有原始信息,但只需要添加。

EN

回答 2

Stack Overflow用户

发布于 2015-10-30 16:43:55

您可以使用XML::Twig来完成此操作。下面的代码迭代所有HostProperties节点,并检查它们是否存在名为mac-addresstag,如果不存在,则插入一个。

代码语言:javascript
运行
复制
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_file替换->parse(\*DATA),并可能添加一些随机的mac地址。

票数 0
EN

Stack Overflow用户

发布于 2015-10-30 19:06:26

好的,我在perlmonks上回答了这个问题,我将通过一个更多的XML示例来重复这个答案。对于这个技巧,我将使用xpath来查询您的XML,而不是遍历树。这背后的原因是因为xpath允许您在一条语句中查询元素、属性和属性内容。

代码语言:javascript
运行
复制
#!/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 ); 
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33425953

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档