使用Perl解析XML中的嵌套属性,哪种方法最佳?

3

我正在处理一个XML文件,它基本上包含一个嵌套元素数组,每个元素都有许多嵌套属性:

<Export land_name="tx">
<Area>
    <Location name="foo"
              square_feet="10,000"
              highway="I-35"/>
    <Location name="dog"
              square_feet="20,000"
              highway="I-45"/>
</Area>
</Export>

我的目标是解析出属性(square_feet、highway、name)并将它们输出到 .csv 文件中。我正在使用 XML::Simple,但我越用它,就越觉得我使用了错误的包。我的主要问题是什么控制结构最好用于解析嵌套的属性?我一直被引用不存在的哈希引用或数组引用所困扰。以下是我目前的代码:

use warnings;
use XML::Simple;
use Data::Dumper;
my $in = "XML_in.xml";
my $xml = XML::Simple->new(KeyAttr => [], ForceArray => [Device], KeepRoot => 1 );
my $Inv = $xml->XMLin($in);
print $Inv->{Export}->{Area}->{Location}->[0]->{name};

如果我的代码存在错误,是因为使用了不正确的 KeyAttrForceArraykeeproot 吗?

2
是的,你是。即使文档上说不要使用它。 :) - simbabque
同时,欢迎来到 Stack Overflow!这是一个非常好的第一个问题。 :) - simbabque
没有嵌套属性这种东西?!? - ikegami
2个回答

5

XML::Simple的文档中不建议在新代码中使用。这是一个很好的例子。您可以使用XML::Twig,它有广泛的文档支持。

use strict;
use warnings;
use feature 'say';
use XML::Twig;

my $twig = XML::Twig->new(
  twig_handlers => {
    'Location' => sub {
      my ( $twig, $elem ) = @_;
      say join ';', map { $elem->att($_) } qw( name square_feet highway );
    },
});

$twig->parse( \*DATA );

__DATA__
<Export land_name="tx">
<Area>
    <Location name="foo"
              square_feet="10,000"
              highway="I-35"/>
    <Location name="dog"
              square_feet="20,000"
              highway="I-45"/>
</Area>
</Export>

这定义了一个针对<Location>标签的处理程序,并从标签中获取了三个属性。你可以根据需要进行操作。
因为你想将它们写入CSV文件,所以可以使用Text::CSV。在外部设置并调用它来在处理程序中写入内容。
另请参阅:

为了确保我能理解代码,你正在使用XML::Twig->new创建一个对象,并设置参数以抓取位置标签内的任何内容,qw是什么,如果我有更多属性要处理,我是否需要列出它们所有? - JustaRedShirt
qw( ... ) 相当于 split(' ', q( ... )) - ikegami
1
是的,你必须列出它们。否则你怎么能确保它们按照你想要的顺序呢? - ikegami
我不确定@ikegami提供的解释有多少帮助。qw从引用的单词中构建一个列表。它与('name','square_feet','highway')相同。 - simbabque
我一直收到一个关于“use”在行中不允许使用的错误(使用XML::Twig),但我不确定这是如何创建错误的。在(use feature 'say')之后应该加上分号吗? - JustaRedShirt
显示剩余2条评论

4

XML::简单:

# ForceArray => [qw( Location )],
# KeyAttr    => [],
# KeepRoot   => 1,

for my $node (@{ $doc->{Export}{Area}{Location} }) {
   say join ';',
      map { $node->{$_} }
         qw( name square_feet highway );
}

XML::Simple要求您进行所有配置,并存在许多陷阱。该模块的文档建议您因此避免使用XML::Simple。

XML::LibXML:

for my $node ($doc->findnodes('/Export/Area/Location')) {
   say join ';',
      map { $node->getAttribute($_) }
         qw( name square_feet highway );
}

XML::Twig:

my $twig = XML::Twig->new(
   twig_handlers => {
      '/Export/Area/Location' => sub {
         my ($twig, $elem) = @_;
         say join ';',
            map { $elem->att($_) }
               qw( name square_feet highway );
      },
   },
);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接