【问题标题】:What's the best way to parse nested attributes in XML using Perl?使用 Perl 解析 XML 中嵌套属性的最佳方法是什么?
【发布时间】:2015-11-03 22:51:49
【问题描述】:

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

如果我的代码有误,是否是 KeyAttrForceArray 或 keeproot 的错误使用?

【问题讨论】:

  • 是的,你是。甚至文档都说不要使用它。 :)
  • 另外,欢迎来到 Stack Overflow!这是一个非常好的第一个问题。 :)
  • 没有嵌套属性之类的东西?!?

标签: xml perl parsing attributes elements


【解决方案1】:

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>

这为&lt;Location&gt; 标签定义了一个处理程序,并从标签中获取三个属性。然后你就可以对它们做你想做的事了。

由于您想将它们写入 CSV 文件,您可以使用Text::CSV。在外面设置它并调用它在处理程序中写东西。

另见:

【讨论】:

  • 为了确保我能理解代码,您正在使用 XML::Twig->new 创建一个对象并设置参数以获取位置标签中的任何内容,什么是 qw,如果我有更多属性可以使用,我必须全部列出吗?
  • qw( ... )split(' ', q( ... )) 相同
  • 是的,您必须列出它们。您还要如何确保它们符合您想要的顺序?
  • 我不确定这个解释对@ikegami 有多大帮助。 qw 从引用的单词构造一个列表。它等同于 ('name', 'square_feet', 'highway')。
  • 您提供的解释适用于一种情况。我提供了适用于所有情况的解释。 (除了我应该把整个东西放在括号里。)
【解决方案2】:

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 );
      },
   },
);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-02
    • 2010-09-30
    • 2016-03-30
    • 1970-01-01
    • 2010-10-28
    • 2011-11-30
    • 1970-01-01
    相关资源
    最近更新 更多