Not an ARRAY reference when using Perl's XML::

2019-08-03 20:50发布

I am getting into XML::Simple and have had a problem with the XML::Simple module choking when parsing one record. The perl code is below.....

#!/usr/bin/perl
# use module
use warnings;
use strict;
use XML::Simple;
use Data::Dumper;

# create object
my $xml = new XML::Simple;

# read XML file
my $data = $xml->XMLin("owners.xml");

foreach my $e (@{$data->{Owner}})
{
     print $e->{OwnerId}->{OwnerCik}."\n";
     print $e->{OwnerId}->{OwnerName}."\n";
     print "\n";
}

When I use this XML, it works beautifully...

<?xml version="1.0"?>
<ownershipDocument>
    <Owner>
        <OwnerId>
            <OwnerCik>0001234878</OwnerCik>
            <OwnerName>PUBLIC JOHN Q</OwnerName>
        </OwnerId>
    </Owner>
    <Owner>
        <OwnerId>
            <OwnerCik>0001234877</OwnerCik>
            <OwnerName>PUBLIC JANE Q</OwnerName>
        </OwnerId>
    </Owner>
</ownershipDocument>

It's when I have a one record that I have issues... the XML below is an example...

<?xml version="1.0"?>
<ownershipDocument>
    <Owner>
        <OwnerId>
            <OwnerCik>0001234878</OwnerCik>
            <OwnerName>PUBLIC JOHN Q</OwnerName>
        </OwnerId>
    </Owner>
</ownershipDocument>

The error I get when parsing this is.....

Not an ARRAY reference at ./so_parse.pl line 14.

I thought the solution would be to use ForceArray and I changed this to include ForceArray..

my $data = $xml->XMLin("so_single.xml", ForceArray=>1);

Now I get ......

Not a HASH reference at ./so_parse.pl line 16.

Admittedly, I'm a little hazy on complex data structures but what I'm trying to solve is how to parse these owners when we only have one.

Any help would be great! Janie

标签: xml perl parsing
2条回答
不美不萌又怎样
2楼-- · 2019-08-03 21:33

Try this:

my $data = $xml->XMLin("so_single.xml", ForceArray=>['Owner']);

It should only force the array on the 'Owner' elements.

查看更多
混吃等死
3楼-- · 2019-08-03 21:38

This is logic and normal. In the first XML file, you have multiple owners, and not in the second XML file. When you do

my $data = $xml->XMLin("owners.xml");

you "convert" the XML in a Perl data structure, and the repeated nodes are in a Perl array, not the others.

What you can do instead :

#!/usr/bin/perl
# use module
use warnings;
use strict;
use XML::Simple;
use Data::Dumper;

# create object
my $xml = new XML::Simple;

# read XML file
my $data = $xml->XMLin("owners.xml");

# if $data->{Owner} is an ARRAY ref
if (ref($data->{Owner}) =~ /ARRAY/) {
    foreach my $e (@{$data->{Owner}}) {
         print $e->{OwnerId}->{OwnerCik}."\n";
         print $e->{OwnerId}->{OwnerName}."\n";
         print "\n";
    }
} else {
    print $data->{Owner}->{OwnerId}->{OwnerCik}."\n";
    print $data->{Owner}->{OwnerId}->{OwnerName}."\n";
}
查看更多
登录 后发表回答