I have curious problem I can't get around. Can you please see what I am doing wrong. I am trying to build an XML in Perl using XML::LibXML. All works fine until I start building sub routine and pass arguments.
First The code that works
my $root = $doc->createElement("XML_FILE");
my @sortedOuterTags = qw ( JMS_VERSION
FILE_NAME
SUBMIT_BY
SUBMIT_DATE
);
# Use hash slice to access the list in hash elements
# Remember has elements are accessed randomly, hence hash slice-ing
my %outHashTags;
@outHashTags { @sortedOuterTags } = ( 'data1',
'data2',
'data3',
'data3');
for my $name (@sortedOuterTags) {
my $outTag = $doc->createElement($name);
my $outValue = $outHashTags{$name};
$outTag->appendTextNode($outValue);
$root->appendChild($outTag);
}
Builds output:
<JMS_VERSION>data1</JMS_VERSION>
<FILE_NAME>data2</FILE_NAME>
<SUBMIT_BY>data3</SUBMIT_BY>
<SUBMIT_DATE>data4</SUBMIT_DATE>
Now the error:
As soon as I spin off for loop to an sub routine as show below I get errors. I am passing 3 paramenters. 1) can't get array values of storedReportTag 2) can't get %reportHashTag data 3) $report element is empty
Code:
buildXMLElements(\@sortedReportTag, %reportHashTags, $report);
sub buildXMLElements() {
my( @elementTags, %hashTags, $parentElement) = @_;
for my $name (@elementTags) {
my $reportTag = $doc->createElement($name);
my $reportValue = $hashTags{$name};
$reportTag->appendTextNode($reportValue);
$parentElement->appendChild($reportTag);
}
}
I want to put in sub as I have several tags to build to re-use the code. I tried passing parameters both directly and as reference.......
Thank you
Update:
After editing my Sub it now looks like this:
buildXMLElements(\@sortedReportTag, \%reportHashTags, $report);
sub buildXMLElements() {
my($elementTags, $hashTags, $parentElement) = @_;
for my $name (@$elementTags) {
my $reportTag = $doc->createElement($name);
my $reportValue = $hashTags->[$name];
$reportTag->appendTextNode($reportValue);
$parentElement->appendChild($reportTag);
}
}
it dies at the line:
my $reportValue = $hashTags->[$name];
Final update:
With Jim's help I corrected the code: Here is final version that works
buildXMLElements(\@sortedReportTag, \%reportHashTags, $report);
sub buildXMLElements() {
my($elementTags, $hashTags, $parentElement) = @_;
for my $name (@$elementTags) {
my $reportTag = $doc->createElement($name);
my $reportValue = $hashTags->{$name};
$reportTag->appendTextNode($reportValue);
$parentElement->appendChild($reportTag);
}
}
buildXMLElements(\@sortedReportTag, %reportHashTags, $report);
...
sub buildXMLElements() {
my( @elementTags, %hashTags, $parentElement) = @_;
You can't do that. The entire contents of @_
will be assigned to @elementTags
. To pass arrays or hashes to a subroutine you must pass a reference. Try instead
buildXMLElements(\@sortedReportTag, \%reportHashTags, $report);
...
sub buildXMLElements() {
my( $elementTags, $hashTags, $parentElement) = @_;
Now, in the subroutine $elementTags
is an array reference, and $hashTags
is a hash reference. To refer to an element of elementTags
use $elementTags->[$i]
or to refer to the entire array do @$elementTags
.
Likewise, for reportHashTags
key lookup use $hashTags->[$key]
, or for the entire hash use %$hashTags
.