Tutorial :How do I retrieve tag attributes with XML::Simple?



Question:

I am simply trying to retrieve an attribute from XML into my Perl program. However, I am having problems retrieving attributes.

I am using XML::Simple.

I can recover information fine when XML is like this:

<IdList>      <Id>17175540</Id>  </IdList>  

by using this code

 $data->{'DocSum'}->{'Id'};  

However, when the XML is like this:

<Item Name="Title" Type="String">      Some Title  </Item>  

I am not getting any data back when using the following code

$data->{'DocSum'}->{'Title'};  

BTW, this is the link I am getting the XML from http://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?db=pubmed&id=19288470


Solution:1

I took the xml from that page you provided, used the entire thing as a string for the argument to XMLin, and had success with

print $data->{DocSum}->{Item}->[5]->{content};  

giving the output

Bromoxynil degradation in a Mississippi silt loam soil.

This is pretty much the same thing derobert was saying.

Edit:

Rather than assuming the 6th Item element is the one you are after, to print the content of the node where the Name attribute is 'Title' (and then break out of the loop since you've found what you want):

foreach my $item_node (@{$data->{DocSum}->{Item}})  {      if($item_node->{Name} eq 'Title')      {          print $item_node->{content};          last;      }  }  

Of course, this is still only looking at the Item nodes immediately under DocSum, so if you were looking for PubType instead of Title, it wouldn't be found due to that being a child of the PubTypeList Item node.


Solution:2

run:

$ perl -MXML::Simple -M'Data::Dump qw/pp/'   my $ref = XMLin('<Item Name="Title" Type="String">Some Title</Item>');  pp $ref;  

output:

{ Name => "Title", Type => "String", content => "Some Title" }  

So, it appears you should be looking under 'content' to find it.


Solution:3

But of course, 'Title' is not a key, but an attribute value, and thus a hash value. You need XPath and then you can specify /DocSum/Item[@Name='Title']

The equivalent in XML::Simple (or Perl), is

my ( $item ) = grep { $_->{Name} eq 'Title' } @{$data->{DocSum}{Item}};  

or even

use List::Util qw<first>;  ...  ( first { $_->{Name} eq 'Title' } @{$data->{DocSum}{Item}} )->{content};  

I have to disagree with daotoad. It's not transforming the data wrong as far as I can see. You're just not working with what it produces correctly. It's a Simple module, it's not robust, and not too DWIM.


Solution:4

I guess you are using XML::Simple to parse XML. I would suggest that you dump your data structure using Data::Dumper. You should be able to find it pretty easily then.

use Data::Dumper;  print Dumper($data);  


Solution:5

It looks like XML::Simple is guessing wrong about how to transform the data. Have you tried munging the KeyAttr option of XMLin()?


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »