http://www.perlmonks.org?node_id=1023199

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

Dear Monks,

I recently started dealing with a bunch of deeply nested XML documents that I'm having to parse and generate reports from. The code works and does the job, but I think that I'm going about it the wrong way - the code I've created is an ugly, inflexible mess of for loops and crazy long references. My guess is that there's a better way. I would deeply appreciate any pointers in a better direction.

Here are the details:

I've used XML::Simple to convert the XML into data structures like so:

my $data = $xml->XMLin("$fail", ForceArray => 1);

I'm then recursing through the data structure like so. It's super ugly:

my $numclients = @{$data->{items}[0]->{client}}; for (my $i=0; $i<$numclients; $i++) { my $clientname = $data->{items}[0]->{client}[$i]->{name}[0]; my $numsites = @{$data->{items}[0]->{client}[$i]->{site}}; for (my $s=0; $s<$numsites; $s++) { my $sitename = $data->{items}[0]->{client}[$i]->{site}[$s]->{name} +[0]; my $numservs = @{$data->{items}[0]->{client}[$i]->{site}[$s]->{ser +vers}}; my %servers; my @fails; my $report; for (my $sv=0; $sv<$numservs; $sv++) { if ($data->{items}[0]->{client}[$i]->{site}[$s]->{servers} +[$sv]->{server}[0]->{name}[0]) { my $server = $data->{items}[0]->{client}[$i]->{site}[$ +s]->{servers}[$sv]->{server}[0]->{name}[0]; eval { my $numfails = @{$data->{items}[0]->{client}[$i]-> +{site}[$s]->{servers}[$sv]->{server}[0]->{failed_checks}}; for (my $fc=0; $fc<$numfails; $fc++) { my $numchecks = @{$data->{items}[0]->{client}[ +$i]->{site}[$s]->{servers}[$sv]->{server}[0]->{failed_checks}[$fc]->{ +check}}; for (my $check=0; $check<$numchecks; $check++) + { if ($data->{items}[0]->{client}[$i]->{site +}[$s]->{servers}[$sv]->{server}[0]->{failed_checks}[$fc]->{check}[$ch +eck]->{dsc_247}[0] == 1) { my $description = $data->{items}[0]->{cl +ient}[$i]->{site}[$s]->{servers}[$sv]->{server}[0]->{failed_checks}[$ +fc]->{check}[$check]->{description}[0]; if ($description !~ /Performance Monit +oring/ ) { push (@fails, $description); $report = 1; } } } } }; # End eval eval { if ( @{$data->{items}[0]->{client}[$i]->{site}[$s] +->{servers}[$sv]->{server}[0]->{overdue}[0]->{description}[0]} ) { my $overdue_ref = @{$data->{items}[0]->{client}[$i +]->{site}[$s]->{servers}[$sv]->{server}[0]->{overdue}[0]->{descriptio +n}[0]}; push (@fails, $overdue_ref); $report=1; } }; # end eval