使用Perl解析XML中嵌套属性的最佳方法是什么?

时间:2015-08-11 15:50:02

标签: xml perl parsing attributes elements

所以我在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};

如果我的代码出错,是KeyAttrForceArra y或keeproot的使用不正确吗?

2 个答案:

答案 0 :(得分:5)

XML::Simple docs say not to use it in new code。这是一个很好的例子。相反,您可以使用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。在外面设置并调用它来在处理程序中写东西。

另见:

答案 1 :(得分: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 ::嫩枝:

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