views:

228

answers:

3

Hello.

My data.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<catalog>
  <cd country="UK">
    <title>Hide your heart</title>
    <artist>Bonnie Tyler</artist>
    <price>10.0</price>
  </cd>
  <cd country="CHN">
    <title>Greatest Hits</title>
    <artist>Dolly Parton</artist>
    <price>9.99</price>
  </cd>
  <cd country="USA">
    <title>Hello</title>
    <artist>Say Hello</artist>
    <price>0001</price>
  </cd>
</catalog>

my test.pl

#!/usr/bin/perl

   # use module
   use XML::Simple;
   use Data::Dumper;

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

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

   # access XML data
   print "$data->{cd}->{country}\n";
   print "$data->{cd}->{artist}\n";
   print "$data->{cd}->{price}\n";
   print "$data->{cd}->{title}\n";

Output:

Not a HASH reference at D:\learning\perl\t1.pl line 16.

Comment: I googled and found the article(handle single xml record). http://www.go4expert.com/forums/showthread.php?t=812 I tested with the article code, it works quite well on my laptop.

Then I created my practice code above to try to access multiple record. but failed. How can I fix it? Thank you.

+2  A: 

If you do print Dumper($data), you will see that the data structure does not look like you think it does:

$VAR1 = {
          'cd' => [
                  {
                    'country' => 'UK',
                    'artist' => 'Bonnie Tyler',
                    'price' => '10.0',
                    'title' => 'Hide your heart'
                  },
                  {
                    'country' => 'CHN',
                    'artist' => 'Dolly Parton',
                    'price' => '9.99',
                    'title' => 'Greatest Hits'
                  },
                  {
                    'country' => 'USA',
                    'artist' => 'Say Hello',
                    'price' => '0001',
                    'title' => 'Hello'
                  }
                ]
        };

You need to access the data like so:

print "$data->{cd}->[0]->{country}\n";
print "$data->{cd}->[0]->{artist}\n";
print "$data->{cd}->[0]->{price}\n";
print "$data->{cd}->[0]->{title}\n";
Ether
+5  A: 

Always use strict;, always use warnings; Don't quote complex references like you're doing. You're right to use Dumper;, it should have shown you that cd was an array ref - you have to specificity which cd.

#!/usr/bin/perl
use strict;
use warnings;

# use module
use XML::Simple;
use Data::Dumper;

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

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

# access XML data
print $data->{cd}[0]{country};
print $data->{cd}[0]{artist};
print $data->{cd}[0]{price};
print $data->{cd}[0]{title};
Evan Carroll
@Evan, Thanks for detail dissection.
Nano HE
+1  A: 

In addition to what has been said by Evan, if you're unsure if you're stuck with one or many elements, ref() can tell you what it is, and you can handle it accordingly:

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

if(ref($data->{cd}) eq 'ARRAY')
{
   for my $cd (@{ $data->{cd} })
   {
      print Dumper $cd;
   }
}
else # Chances are it's a single element
{
   print Dumper $cd;
}
squeeks