我正在使用Perl的XML::Simple来解析深层嵌套的XML,并希望提取一个关于4个级别的元素的小列表:
A
B
C
D1
D2
D3
理想情况下,如果可能,我想在输入步骤中执行此操作。像这样:
my @list = XMLin($xml, { SomeAttribute => 'ButWhat?' });
以与我相同的方式结束:
@list = ('D1', 'D2', 'D3')
有可能吗?或者只是不那么“简单”?
答案 0 :(得分:3)
假设您的内存数据如下:
my $parsed = {
A => {
B => {
C => [ qw/here is your list/ ],
},
},
};
然后,您可以使用my @list = @{ $parsed->{A}{B}{C} }
获取列表。
这是你想要做的吗?
编辑:考虑到一些评论,也许你想要的 Data::Visitor::Callback。 然后,您可以提取所有数组,如:
my @arrays;
my $v = Data::Visitor::Callback->new(
array => sub { push @arrays, $_ },
);
$v->visit( $parsed_xml );
运行之后,\ @arrays将是一个引用列表 任意深度嵌套的数组。
最后,如果您只有一个属性名称并想要搜索 匹配XML节点,你真的想要XPath:
use XML::LibXML;
my $parser = XML::LibXML->new;
my $doc = $parser->parse_string( $xml_string );
# yeah, I am naming the variable data. so there.
my @data = map { $_->textContent } $doc->findnodes('//p[@id="foo"]');
无论如何,TMTOWTDI。如果您正在使用XML,并且想要这样做 复杂的东西,XML :: Simple很少是正确的答案。我用 XML :: LibXML适用于所有内容,因为它几乎总是更容易。
还有一件事,你可能想要 Data::DPath。它让 你“XPath”是一个内存中的perl数据结构:
答案 1 :(得分:1)
在Jon's answer上构建,这是我在需要做这类事情时使用的基本代码。如果我需要更高级的东西,如果我被允许这样做,我通常会找到一个模块。
get_values
中的技巧从顶级引用开始,获得下一个较低级别,并将其放在同一个变量中。它一直持续到我到达我想去的地方。大多数代码只是断言,以确保事情正常运行。在大多数情况下,我发现它是混乱的数据,而不是遍历(但我做了大量的数据清理工作)。根据您的情况调整错误检查。
use Carp qw(croak); my $parsed = { A => { B => { C => [ qw/here is your list/ ], D => { E => [ qw/this is a deeper list/ ], }, }, }, }; my @keys = qw( A B C D ); my @values = eval { get_values( $parsed, @keys ) } or die; $" = " ][ "; print "Values are [ @values ]\n"; sub get_values { my( $hash, @keys ) = @_; my $v = $hash; # starting reference foreach my $key ( @keys ) { croak "Value is not a hash ref [at $key!]\n" unless ref $v eq ref {}; croak "Key $key does not exist!\n" unless exists $v->{$key}; $v = $v->{$key}; # replace with ref down one level } croak "Value is not an array ref!" unless ref $v eq ref []; @$v; }
答案 2 :(得分:0)
您使用XML :: Simple这一事实无关紧要;你正试图搜索有refs和数组引用的结构。你知道你在寻找什么吗?它会永远在同一个地方吗?如果是这样的话,那么jrockway写的东西很容易就能解决问题。如果没有,那么你需要走完每个结构,直到找到你想要的东西。
我经常做的一件事是转储XML :: Simple使用Data::Dumper返回的结构,看看它看起来像什么(如果它总是“看起来”相同;如果没有,你可以动态地确定如何通过测试走它是一个参考,它是什么样的参考)。真正的问题是:你在寻找什么?
答案 3 :(得分:0)
Data::Diver为挖掘深层结构提供了一个很好的界面。
答案 4 :(得分:0)
感谢所有建议。
最后,我通过使用eval块避免了遍历数据结构的问题。
my $xml_tree;
my @list;
eval {
# just go for it
my @list = @{ $xml_tree->{A}->{B}->{C} };
};
if ($@) {
say "oops - xml is not in expected format - and that happens sometimes";
}