use strict; use warnings; use XML::Simple; my $xml_raw = < Todd Katherine Tilbuster Ponds Maribyrnong Patterson Paterson Glenelg Murray Bunyip Campaspe Eucumbene Mulla Mulla Creek Burrungubugge Goobarragandra Bombala Murray Emu Swamp Creek XML_RAW my $xml_hash_ref = XMLin($xml_raw, KeepRoot=>1); my %xml_hash = %{$xml_hash_ref}; my ($tl_hk, $tl_hv) = each %xml_hash; my $last_key = ''; my @key_stash = (); my $ref_type = ''; my $fish_species = ''; my $fish_survey_dump =""; # Just to show you how XML::Simple has structured the XML into a hash #use Data::Dumper; #print Dumper(\%xml_hash); traverse_hash($xml_hash{$tl_hk}, $tl_hk); # Print out the fish survey information that we wanted. # I concatenated it into a scalar just for quick display purposes print "\n\n$fish_survey_dump\n"; sub traverse_hash { my ($hash_val, $last_key) = @_; push(@key_stash, "$last_key ->"); for my $key (keys %{$hash_val}) { $ref_type = ref($hash_val->{$key}) || "VALUE"; print "$ref_type: @key_stash $key -> ", $hash_val->{$key},"\n"; if($ref_type eq 'HASH') { if($key=~/barramundi|carp|yellowfin/) { $fish_species = $key; concat("\n\n[ Survey information for: $fish_species ]:\n\n"); concat("Saltwater:" . $hash_val->{$fish_species}{'saltwater'} . "\n"); concat("Freshwater:" . $hash_val->{$fish_species}{'freshwater'} . "\n"); concat("Rivers covered in survey:\n\n"); for my $river (@{$hash_val->{$fish_species}->{'river'}}) { concat("$river\n"); } } $last_key = $key; # Loop through any sub hash's by calling traverse_hash() agian. traverse_hash($hash_val->{$key}, $last_key); pop(@key_stash); }elsif($ref_type eq 'ARRAY') { # Array reference traverse_array($key, @{$hash_val->{$key}}); }else{ # Hash value; # ... } } } sub traverse_array { my ($key, @array) = @_; for my $array_val (@array) { print "ARRAY-VAL: @key_stash $key -> ", $array_val,"\n"; if(ref($array_val) eq 'HASH') { traverse_hash($array_val, undef); } } } sub concat { my $string = $_[0]; $fish_survey_dump .= $string; }