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

OK, I apparently am not very smart because I can't seem to post things right... Here is what I wanted to post.

Let me start this off by saying that I am not a Perl programmer, but can, and I guess do, program in Perl from time to time. My code in Perl is usually a little redundant and could easily be improved. I am asking for help.

I have some code that I built to parse an XML Doc/Node and return a number of responses based on a qualifier. It uses the XML::DOM parser that is downloadable from CPAN. The code is posted below and could benefit some I guess by providing a method of mapping a path through a typical XML document or node.

Please pardon the lacking comments.

Here is the code. Function Calls are at the bottom. Anyone see where I could fix/clean this up?


#!/usr/bin/perl -w use strict; use XML::DOM; use Data::Dumper; my $parser = new XML::DOM::Parser; my $doc = $parser->parsefile ("samplexml.xml"); my $root = $doc->getDocumentElement(); ########################################################### sub traverse { my($node)= @_; if ($node->getNodeType == ELEMENT_NODE) { print Dumper (get_children_hash_by_node($node)); my $rot_hash = get_children_hash_by_node($node); if ($rot_hash) { foreach my $child ($rot_hash->{children}) { traverse($child); } } } } ########################################################### ########################################################### sub get_children_hash_by_node($) { my ($node)=@_; my $this_node; my $att_hash; my @children; my @children_names, my $node_data; if ($node->getNodeType == ELEMENT_NODE) { my $textNode = $node->getFirstChild(); if ($textNode) { $node_data = $textNode->getNodeValue(); } $this_node = $node->getNodeName; my $atts = $node->getAttributes(); #print $this_node."\n"; my $thisItem = 0; while ($atts->item($thisItem)){ $att_hash->{$atts->item($thisItem)->getNodeName() +}->{value} = $atts->item($thisItem)->getNodeValue(); $thisItem++; } foreach my $child ($node->getChildNodes()) { if ($child->getNodeType == ELEMENT_NODE){ push (@children, $child); push (@children_names, $child->getNodeName()); } } } my $ret_node = { name => $this_node, attributes => $att_hash, value => $node_data, children_names => \@children_names, children => \@children, }; return $ret_node; } ########################################################### ########################################################### sub get_x_info($ $ $) { my ($xdoc, $xpath, $data)=@_; #get_x_info(('node_name|1','child_node|0','child_node|0') , 'ALL') +; #'ALL' returns hash with all of the following #'ATTS' returns attributes hash #'VALUE' returns value of the node #'NAME' returns node name as string #'CHILD_NAMES' returns an array of strings #'CHILDREN' returns an array of hashes #'EXISTS' my $ret_val; my $iter = 0; my ($xnode, $i) = split (/\|/,@{$xpath}[0]); if (!$i){$i=0;} shift(@{$xpath}); my $rot_node = get_children_hash_by_node($xdoc); if ($xnode eq $rot_node->{name}) { if (@{$xpath}[0]) { ($xnode, $i) = split (/\|/,@{$xpath}[0]); if (!$i){$i=0;} foreach my $child ( @{$rot_node->{children}} ) { if ($child and ($child->getNodeName() eq $xnode) and $ +iter != $i) { $iter++; } elsif ($child and ($child->getNodeName() eq $xnode) an +d $iter == $i) { $ret_val = &get_x_info($child, \@{$xpath}, $data); last; } else { $ret_val = ($xnode." node does not exist"); } } } else { if ($data eq 'ALL') { $ret_val = $rot_node; } elsif ($data eq 'ATTS') { $ret_val = $rot_node->{attributes}; } elsif ($data eq 'VALUE') { $ret_val = $rot_node->{value}; } elsif ($data eq 'NAME') { $ret_val = $rot_node->{name}; } elsif ($data eq 'CHILD_NAMES') { $ret_val = $rot_node->{children_names}; } elsif ($data eq 'CHILDREN') { $ret_val = $rot_node->{children}; } elsif ($data eq 'NODE') { $ret_val = $xdoc; } elsif ($data eq 'EXISTS') { $ret_val=""; } } } return $ret_val; } ########################################################### #print "\n-----------------------------------------------------\n"; #traverse($root); #print Dumper (get_x_info($root,['SOAP-ENV:Envelope|0','SOAP-ENV:Heade +r|0'],'CHILD_NAMES')); #print Dumper (get_children_hash_by_node($root)); print Dumper (get_x_info($root, [ 'SOAP-ENV:Envelope', 'SOAP-ENV:Body', 'SOAPSDK1:AdminRequestResponse', 'Result', 'getTransactionResponse', 'transactions', 'transaction|3', 'referenceNumber' ], 'NODE'));


By the way, I just wanted to explain the function of get_x_info($$$)

get_x_info(var1, var2, var3)

var1 is the XML-DOM node or document being passed in for parsing.

var2 is an array indicating the path in which you would like to query the document. An element with a pipe (|) and following integer reflects a specific iteration of the node which might repeat. in the case above it is the 4th 3rd instance of node named 'transaction'.

var3 is a qualifier indicating the type of data returned.