Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Trouble Getting Deep Into a Hash from XML::Simple

by inblosam (Monk)
on Sep 02, 2006 at 06:24 UTC ( [id://570859]=perlquestion: print w/replies, xml ) Need Help??

inblosam has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to handle the data coming from the Adwords API with XML::Simple, which seems to be a decent choice for it, but I can't seem to grab the values that I need, which are just so deep into the XML. I'm not sure where I'm wrong, but maybe you can help:
#!/usr/bin/perl -w use strict; use XML::Simple; use Data::Dumper; my $content = XMLin(qq| <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envel +ope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http:// +www.w3.org/2001/XMLSchema-instance"> <soapenv:Header> <responseTime soapenv:actor="http://schemas.xmlsoap.org/soap/actor/n +ext" soapenv:mustUnderstand="0" xmlns="https://adwords.google.com/api +/adwords/v5">124</responseTime> <operations soapenv:actor="http://schemas.xmlsoap.org/soap/actor/nex +t" soapenv:mustUnderstand="0" xmlns="https://adwords.google.com/api/a +dwords/v5">1</operations> <units soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next" so +apenv:mustUnderstand="0" xmlns="https://adwords.google.com/api/adword +s/v5">25</units> <requestId soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next +" soapenv:mustUnderstand="0" xmlns="https://adwords.google.com/api/ad +words/v5">123</requestId> </soapenv:Header> <soapenv:Body> <getKeywordVariationsResponse xmlns="https://adwords.google.com/api/ +adwords/v5"> <getKeywordVariationsReturn> <moreSpecific> <text>web content managment</text> <language>en</language> <advertiserCompetitionScale>3</advertiserCompetitionScale> <searchVolumeScale>1</searchVolumeScale> </moreSpecific> <moreSpecific> <text>web based content management</text> <language>en</language> <advertiserCompetitionScale>5</advertiserCompetitionScale> <searchVolumeScale>1</searchVolumeScale> </moreSpecific> <additionalToConsider> <text>3.14</text> <language>en</language> <advertiserCompetitionScale>3</advertiserCompetitionScale> <searchVolumeScale>2</searchVolumeScale> </additionalToConsider> <additionalToConsider> <text>babinet's</text> <language>en</language> <advertiserCompetitionScale>2</advertiserCompetitionScale> <searchVolumeScale>0</searchVolumeScale> </additionalToConsider> </getKeywordVariationsReturn> </getKeywordVariationsResponse> </soapenv:Body> </soapenv:Envelope> |); print "... $content->{'soapenv:Envelope'}{'soapenv:Body'}{'getKeywordV +ariationsResponse'}{'getKeywordVariationsReturn'}{'moreSpecific'}[0]- +>{'text'} ...\n"; #print Dumper(\$content);
This returns me nothing, and I even get the fun uninitialized statement:
Use of uninitialized value in concatenation (.) or string at xmlparser +.pl line 54.
Any ideas? Obviously I need what's in the text, advertiserCompetitionScale, and searchVolume tags, and I need to iterate through each occurrence. Any ideas?


Michael

Replies are listed 'Best First'.
Re: Trouble Getting Deep Into a Hash from XML::Parser
by runrig (Abbot) on Sep 02, 2006 at 07:12 UTC
    By default the root tag is dropped and not included in the hash. Use the KeepRoot option if you want to include it. Otherwise just use:
    print $content->{'soapenv:Body'}{getKeywordVariationsResponse}{getKeyw +ordVariationsReturn}{moreSpecific}[0]{text},"\n";
    (also note that your title is misleading as this is an XML::Simple question, not really XML::Parser).
      One more associated problem, how do I know how many to expect when I am running through adding each of these to an array of hashes? There's got to be a better way to handle it. The code below works, but the XML has a different number of results each time for the "moreSpecific" tag. Any suggestions??
      my $moreListCnt = 2; my $cnt = 0; my @morelist; for (;$cnt<$moreListCnt;$cnt++) { $morelist[$cnt]{'more'} = $content->{'soapenv:Body'}{'getKeywordVa +riationsResponse'}{'getKeywordVariationsReturn'}{'moreSpecific'}[$cnt +]->{'text'}; $morelist[$cnt]{'comp'} = $content->{'soapenv:Body'}{'getKeywordVa +riationsResponse'}{'getKeywordVariationsReturn'}{'moreSpecific'}[$cnt +]->{'advertiserCompetitionScale'}; $morelist[$cnt]{'pop'} = $content->{'soapenv:Body'}{'getKeywordVar +iationsResponse'}{'getKeywordVariationsReturn'}{'moreSpecific'}[$cnt] +->{'searchVolumeScale'}; }
      Thanks!!


      Michael
        First, I would use ForceArray on the moreSpecific tag (if there is only one 'moreSpecific' node, it will not make an array), and you don't need the count to access all of the subnodes.
        my $morelist = $content->{'soapenv:Body'}{'getKeywordVariationsRespons +e'}{'getKeywordVariationsReturn'}{'moreSpecific'}; for my $more (@$morelist) { print "$more->{text}\n"; print "$more->{advertiserCompetitionScale}\n"; print "$more->{searchVolumeScale}\n"; $more->{more} = $more->{text}; $more->{comp} = $more->{advertiserCompetitionScale}; $more->{pop} = $more->{searchVolumeScale}; }
        Update: fixed, updated example.
      Works like a charm! Thanks for pointing that out, I think I was just looking at some XML::Parser documentation...


      Michael

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://570859]
Approved by graff
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (4)
As of 2024-04-19 02:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found