Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the best way to parse nested attributes in XML using Perl?

So I'm working within an xml file that basically has a nested array of elements with each element having a lot of nested attributes:

<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>

My goal is to parse out the attributes (square_feet, highway, name) and output them to a .csv file. I'm using XML::Simple but the more I've worked with it I think I'm using the wrong package. My main question is what is the best control structure to parse out the nested attributes? I keep getting caught up on referring to non-existent has references or array references. Here is the code I have so far:

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

If my code is in error, is it the incorrect usage of the KeyAttr, ForceArray, or keeproot?

like image 301
JustaRedShirt Avatar asked Dec 01 '25 05:12

JustaRedShirt


1 Answers

The XML::Simple docs say not to use it in new code. This is a good example why. Instead, you can use XML::Twig, which has extensive documentation.

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>

This defines a handler for the <Location> tag, and grabs the three attributes out of the tag. You can then do what you want with them.

Since you want to write them to a CSV file you can use Text::CSV. Set it up outside and call it to write stuff in the handler.

See also:

  • XML::Twig::Elt
like image 198
simbabque Avatar answered Dec 03 '25 22:12

simbabque



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!