Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options

Re: Parsing SOAP::Lite results

by kcott (Canon)
on Sep 28, 2012 at 10:38 UTC ( #996164=note: print w/replies, xml ) Need Help??

in reply to Parsing SOAP::Lite results

G'day Roboz,

You effectively have arrays nested within arrays, so you'll need some sort of nested loops to read the data.

If you change

foreach my $e (@{$getToysResults->{Toys}{Toy}}){ print "$e->{ToyLocations}{ToyLocation}{locationName}\n"; }


foreach my $e (@{$getToysResults->{Toys}{Toy}}) { my $location_array_ref = $e->{ToyLocations}{ToyLocation}; for my $location_array_hash_ref (@$location_array_ref) { print $location_array_hash_ref->{locationName}, "\n"; } }

you'll get the results you're after.

[Aside: On first viewing, I found your naming conventions somewhat counter-intuitive: Toys and ToyLocations are both plural but point to single objects; Toy and ToyLocation are both singular but point to (potentially) multiple objects. In the context of the Dumper output, it's fairly easy to see what's intended; in isolation, those names may easily lead to problems of misinterpretation (particularly if you or someone else revisits the code 12 months down the track).]

-- Ken

Replies are listed 'Best First'.
Re^2: Parsing SOAP::Lite results
by Roboz (Novice) on Sep 28, 2012 at 11:14 UTC

    Tried your suggestion and received a 'Not an ARRAY reference' error on the for my $location_array_hash_ref (@$location_array_ref) {

    Yeah, the naming convention is due to an XML schema I have no control over.

      I tested that code before posting. I changed $VAR1 to my $getToysResults but otherwise left the Dumper output unchanged. Here's the script ( in its entirety:

      #!/usr/bin/env perl use strict; use warnings; my $getToysResults = { 'Toys' => bless( { 'Toy' => [ bless( { 'ToyLocations' => bless( { 'ToyLocation' => [ { 'toyQuantity' => '1', 'locationName' => 'toybox' }, { 'toyQuantity' => '4', 'locationName' => 'shelf' } ] }, 'ArrayOfToyLocation' ), 'color' => 'none', 'toyName' => 'Sorry', 'size' => 'medium' }, 'Board' ) ] }, 'ArrayOfToy' ) }; foreach my $e (@{$getToysResults->{Toys}{Toy}}) { my $location_array_ref = $e->{ToyLocations}{ToyLocation}; for my $location_array_hash_ref (@$location_array_ref) { print $location_array_hash_ref->{locationName}, "\n"; } }

      Here's the output:

      $ toybox shelf

      Try running that script. If it works, then maybe the data you posted was incorrect (typo, cut-and-paste error, etc.) or perhaps you used my code differently. Try adding print Dumper $getToysResults; just before the outer foreach in your code and see if it produces the same output as you originally posted.

      If it doesn't work, please post full output along with your Perl version and OS: as it stands, I can't see anything there that wouldn't work on any version of Perl 5.

      -- Ken

        I see what's causing my issue with the 'Not an ARRAY ref' error. When there is only one location it's not an array.

        $VAR1 = { 'Toys' => bless( { 'Toy' => [ bless( { 'ToyLocations' => bless( { 'ToyLocation' => { 'toyQuantity' => '2', 'locationName' => 'toy +box' } }, 'ArrayOfToyLocation' ), 'color' => 'brown', 'toyName' => 'bear', 'size' => 'large' }, 'Stuffed' ), bless( { 'ToyLocations' => bless( { 'ToyLocation' => [ { 'toyQuantity' => '1', 'locationName' => 'toy +box' }, { 'toyQuantity' => '4', 'locationName' => 'she +lf' } ] }, 'ArrayOfToyLocation' ), 'color' => 'none', 'toyName' => 'Sorry', 'size' => 'medium' }, 'Board' ) ] }, 'ArrayOfToy' ) };

        Still stuck on what to do in this case. Would this be where introspection comes in?  pseudo:(if HASH, then ... %$location) elsif ARRAY, then ... @$location)  ? Thanks to all who are helping me learn this!


      Kcott's code works perfectly.
      Maybe, you are not saving the changes you made to your script.
      However, if the double for loop used confuses you, you can consider this:

      use warnings; use strict; my $getToysResults = { 'Toys' => bless( { 'Toy' => [ bless( { 'ToyLocations' => bless( { 'ToyLocation' => [ { 'toyQuantity' => '1', 'locationName' => 'toybox' }, { 'toyQuantity' => '4', 'locationName' => 'shelf' } ] }, 'ArrayOfToyLocation' ), 'color' => 'none', 'toyName' => 'Sorry', 'size' => 'medium' }, 'Board' ) ] }, 'ArrayOfToy' ) }; foreach my $e ( @{ $getToysResults->{Toys}{Toy} } ) { print join "\n" => map { $_->{locationName} } @{ $e->{ToyLocations}{ToyLocation} }; }

      If you tell me, I'll forget.
      If you show me, I'll remember.
      if you involve me, I'll understand.
      --- Author unknown to me

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://996164]
[Your Mother]: Just Another Perl 'Acker.
[LanX]: I pronounce it 'juːmən'
[Your Mother]: Hey, let's not bring antisemitism into the conversation.
[LanX]: for centuries posh English speakers tried to approach French, that's where all the trouble starts
[Eily]: Just another Perl coeurs
[Eily]: (perl with hearts, 'Acker with a French accent is pronunced like coeurs)
[LanX]: IMHO 'ju' for 'u' happens in English where they can't pronounce the French u (or German )
[LanX]: and I'm sure I read that *hotel* used to be pronounced 'otel by the English upperclass
[Your Mother]: American English vowels are pretty lazy/mumbly in general.
[LanX]: talking about antisemitism, youtube automatic subtitles is entertaining shocking sometimes ... like when offering "Fruit Jews" as a drink

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (8)
As of 2017-03-27 17:13 GMT
Find Nodes?
    Voting Booth?
    Should Pluto Get Its Planethood Back?

    Results (320 votes). Check out past polls.