2

在这里完全是菜鸟,所以我很抱歉我提前的无知。

我搜索和弄乱的大部分内容都集中在使用XML::LibXMLXPath 上。

我遇到的问题是我不希望在标签之间捕获文本:我需要标签的值。

这是我的 XML 结构

<users>
  <entry name="asd">
    <permissions>
      <role-based>
        <superuser>yes</superuser>
      </role-based>
    </permissions>
  </entry>
  <entry name="fgh">
    <permissions>
      <role-based>
        <superuser>yes</superuser>
      </role-based>
    </permissions>
    <authentication-profile>RSA Two-Factor</authentication-profile>
  </entry>
  <entry name="jkl">
    <permissions>
      <role-based>
        <superreader>yes</superreader>
      </role-based>
    </permissions>
    <authentication-profile>RSA Two-Factor</authentication-profile>
  </entry>
</users>

我正在尝试获取名称属性(不带引号)并确定此人是超级用户还是超级读者。

除了打印节点之外,我无法做很多事情。我需要将其转换为用户名结构中的 CSV 文件;角色

4

4 回答 4

5

从 XML 文档中提取信息的最简单方法XML::LibXML是使用find方法族。这些方法使用 XPath 表达式从文档中选择节点和值。以下脚本提取您需要的数据:

use XML::LibXML;

my $doc = XML::LibXML->load_xml(location => 'so.xml');

for my $entry ($doc->findnodes('//entry')) {
    my $name = $entry->getAttribute('name');
    my $role = $entry->findvalue(
        'local-name(permissions/role-based/*[.="yes"])'
    );
    print("$name;$role\n");
}   

它打印

asd;superuser
fgh;superuser
jkl;superreader

我使用local-nameXPath 函数来获取角色元素的名称。

请注意,您可能希望使用Text::CSV更可靠的方式创建 CSV 文件。

于 2013-10-17T18:13:19.020 回答
3

具有不同模块的另一种解决方案XML::Twig

#!/usr/bin/env perl

use warnings;
use strict;
use XML::Twig;

my ($name, $role);

my $twig = XML::Twig->new(
    twig_handlers => {
        'entry' => sub { 
            $name = $_->att('name');
            if ( defined $name && defined $role ) { 
                printf qq|%s;%s\n|, $name, $role;
            }   
            map { undef $_ } ($name, $role);
        },  
        'role-based' => sub { $role = $_->first_child->tag },
    },  
)->parsefile( shift );

像这样运行它:

perl script.pl xmlfile

这会产生:

asd;superuser
fgh;superuser
jkl;superreader
于 2013-10-17T21:57:47.717 回答
2

使用 XML::Rules:

use XML::Rules;

print "name is_superuser is_superreader\n";
my @rules = (
  entry => sub {
    my $entry = $_[1];
    $_ ||= 'no' for @$entry{qw(superuser superreader)};
    print "$entry->{name} $entry->{superuser} $entry->{superreader}\n";
  },
  'permissions,role-based' => 'pass no content',
  'superuser,superreader' => 'content',
  _default => undef,
);

my $p = XML::Rules->new(rules => \@rules);
my $s = $p->parse(doc());

sub doc {
return <<XML;
<users>
   <entry name="asd">
       <permissions>
            <role-based>
                <superuser>yes</superuser>
            </role-based>
       </permissions>
   </entry>
   <entry name="fgh">
       <permissions>
            <role-based>
                <superuser>yes</superuser>
            </role-based>
       </permissions>
       <authentication-profile>RSA Two-Factor</authentication-profile>
   </entry>
   <entry name="jkl">
       <permissions>
            <role-based>
                <superreader>yes</superreader>
            </role-based>
       </permissions>
       <authentication-profile>RSA Two-Factor</authentication-profile>
   </entry>
</users>
XML
}

或者假设您的关键字段的所有内容都是“是”(以及其他一些假设)的一组可选规则:

my $name;
my @rules = (
  '^entry' => sub {
    $name = $_[1]->{name};
  },
  'superuser,superreader' => sub {
    print "$name,$_[0]\n";
  },
  _default => undef,
);
于 2013-10-17T22:18:21.117 回答
1

我喜欢XML::Simple用于这样的项目。

例如:

use XML::Simple;

my $su = $ARGV[0];
die unless (-e $su);

my $su_xml = XMLin($su, ForceArray => [ 'entry' ]);
my $suref = $su_xml->{entry};

foreach my $key (keys %{$suref}) {
    $rb = ${$suref}{$key}->{permissions}->{'role-based'};
    foreach my $rbkey (keys %{$rb}) {
        print "$key\t$rbkey\t${$rb}{$rbkey}\n";
    }
}

印刷:

fgh     superuser       yes
asd     superuser       yes
jkl     superreader     yes
于 2013-10-17T19:10:29.850 回答