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?
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:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With