首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用Perl解析XML

用Perl解析XML
EN

Stack Overflow用户
提问于 2013-10-17 18:00:38
回答 4查看 686关注 0票数 2

所以我为我的无知感到抱歉。

我搜索和处理的大部分内容都是围绕使用XML::LibXML和XPath进行的。

我的问题是,我不想捕捉标签之间的文本:我需要标记的值。

这是我的XML结构

代码语言:javascript
复制
<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>

我试图获取name属性(没有引号),并确定此人是超级用户还是超级读者。

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

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-10-17 18:13:19

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

代码语言:javascript
复制
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");
}   

印出来

代码语言:javascript
复制
asd;superuser
fgh;superuser
jkl;superreader

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

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

票数 5
EN

Stack Overflow用户

发布于 2013-10-17 21:57:47

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

代码语言:javascript
复制
#!/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 );

运行它就像:

代码语言:javascript
复制
perl script.pl xmlfile

这会产生:

代码语言:javascript
复制
asd;superuser
fgh;superuser
jkl;superreader
票数 3
EN

Stack Overflow用户

发布于 2013-10-17 22:18:21

使用XML::Rules:

代码语言:javascript
复制
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
}

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

代码语言:javascript
复制
my $name;
my @rules = (
  '^entry' => sub {
    $name = $_[1]->{name};
  },
  'superuser,superreader' => sub {
    print "$name,$_[0]\n";
  },
  _default => undef,
);
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19433930

复制
相关文章

相似问题

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