How can I get an XML element's attribute with Perl's XML::Simple?

13,521

Solution 1

Well, from the XML you posted, I get this:

Entity: line 3: parser error : Opening and ending tag mismatch: league line 0 and leage

It doesn't even appear to be a strict/warnings issue because it appears when I comment my USUW out.

But if you have the right tags, this should work:

$xml->{game}{name};

And if I call XMLin with KeepRoot => 1, you'll find it at:

    $xml->{league}{game}{name};

If you are having trouble locating how the data is being read in, do this:

use 5.010;
use strict;
use warnings;
use Data::Dumper;
use XML::Simple;

my $xml = XMLin( $input );
say Data::Dumper->Dump( [ $xml ], [ '$xml' ] );

And then use the path to the structures presented.


Note:

$xml->{league}->{game}->['name'];

should have died with: "Not an ARRAY reference at" even without warnings enabled. ['string'] is a reference to an array with the string 'string' as the sole element. And, if $xml->{league}{game} were an array, it would have died with a non-numeric error, because strings don't address arrays.

Solution 2

I normally instantiate my XML::Simple objects like this:

use XML::Simple ':strict';
my $xs = XML::Simple->new( KeepRoot => 1, KeyAttr => 1, ForceArray => 1 );

it allows the structure to be consistent between single and possibly multiple sub-elements. With those settings, this code gets your value:

#!/usr/bin/perl
use strict;
use warnings;
use XML::Simple ':strict';

my $xs = XML::Simple->new( KeepRoot => 1, KeyAttr => 1, ForceArray => 1 );
my $ref = $xs->XMLin('data.xml');
print $ref->{league}[0]{game}[0]{name};

I added another game tag, and an attribute on the league tag as an example, this is the xml:

<league name="baz"> 
    <game name="bla"/>
    <game name="foo"/>
</league>

And the Data::Dumper output is:

$VAR1 = {
          'league' => [
                      {
                        'game' => [
                                  {
                                    'name' => 'bla'
                                  },
                                  {
                                    'name' => 'foo'
                                  }
                                ],
                        'name' => 'baz'
                      }
                    ]
        };
Share:
13,521
baklap
Author by

baklap

Yeah!

Updated on June 04, 2022

Comments

  • baklap
    baklap almost 2 years

    I have a Perl script that reads a XML file that doesn't have content, only attributes in the element.

    Like this:

    <league>
    <game name="bla"/>
    </league>
    

    Now I try to get the game attribute 'name'.

    I tried using $xml->{league}->{game}->{name} and $xml->{league}->{game}->['name'] but they are both not working. Something about a hash problem.

    Is there anybody who can help me get the value?

  • baklap
    baklap over 13 years
    $xml->{game}{name}; gives me a: Not a HASH reference at parser.pl line 22.
  • Axeman
    Axeman over 13 years
    @baklap, see the suggestion for Data::Dumper.
  • baklap
    baklap over 13 years
    thanks, made it output to a file. But I see what's wrong. The xml I posted was just a a quick example, not the real xml. My bad. The thing that is going wrong is that some are {element} things and some are ['name'] (don't know what the difference is) I'm able to print the {element} things, but the ['name'] things arent printable, I don't know how to do that...
  • Axeman
    Axeman over 13 years
    @baklap, I don't understand "['name'] things." What options are you passing to XMLin? If it appeared in the dump as ['name'] then it's the same thing as: $array_ref->[0] = 'name', if you see square brackets, it's in an array--although I don't understand why it wouldn't have the attribute value ("blah" in the toy case) near by it.
  • Grant McLean
    Grant McLean over 13 years
    Setting KeyAttr => 1 doesn't make much sense. Perhaps you mean KeyAttr => {}.
  • Roy van Os
    Roy van Os over 13 years
    KeyAttr => [], rather, I guess '1' would break on XML tags named '1'