Search code examples
xmlperlxml-simple

Trouble with a one-node XML file in Perl


I have many multi-node XML files that I'm parsing with XML::Simple. So far it works great. One of the first things I do is get the length of the XML file (node count) using this:

my $xmltemp = XML::Simple->new(
    SuppressEmpty => 1
);

my $product = $xmltemp->XMLin('xml/' . $basename . '.xml');

my $qfr = @{ $product->{$basename}};
print "$qfr = qfr\n";

The variable $basename is provided by looping through an array of file names. The nodename and filename are the same.

This works in all the files, except for files that only have one node. The program tanks at the attempt to create the $qfr variable.

If I edit one of the single-node XML files and create another node (dupe the existing one) and rerun, this works fine.

What is wrong that causes a one node XML to not respond to a simple scalar variable assignment?

The print line won't even execute.

NOTE: I cut and pasted the important bits of code from a .pl and and .pm to make it easy to grasp.

EDIT: Here is a single node XML sample:

<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<FUNDDATA>
  <FUND_DATA>
    <ADVISOR_FUND_CUSIP>316146703</ADVISOR_FUND_CUSIP>
    <ADVISOR_FUND_ID>01118</ADVISOR_FUND_ID>
    <ADVISOR_FUND_NAME>Pizza Fund - Class A</ADVISOR_FUND_NAME>
    <ADVISOR_FUND_SASID>01118</ADVISOR_FUND_SASID>
    <ALL_ADVISOR_CLASSES>01118,01123,01124,01125,01126</ALL_ADVISOR_CLASSES>
    <ALL_ADVISOR_CLASSES_CUSIPS>316146703,316146885,316146877,316146802,316146869</ALL_ADVISOR_CLASSES_CUSIPS>
    <ALL_ADVISOR_CLASSES_SASIDS>01118,01123,01124,01125,01126</ALL_ADVISOR_CLASSES_SASIDS>
    <ALL_ADVISOR_CLASSES_TYPES>A,B,C,T,I</ALL_ADVISOR_CLASSES_TYPES>
    <ALL_RETAIL_CLASSES>00026</ALL_RETAIL_CLASSES>
    <ALL_RETAIL_CLASSES_CUSIPS>316146109</ALL_RETAIL_CLASSES_CUSIPS>
    <ALL_RETAIL_CLASSES_SASIDS>00026</ALL_RETAIL_CLASSES_SASIDS>
    <ALL_RETAIL_CLASSES_TYPES>N</ALL_RETAIL_CLASSES_TYPES>
    <BUSINESS_UNIT>CCC</BUSINESS_UNIT>
    <DATE_ID>September 2000</DATE_ID>
    <PRIMARY_FUND_ID>000044</PRIMARY_FUND_ID>
    <RETAIL_FUND_CUSIP>44444</RETAIL_FUND_CUSIP>
    <RETAIL_FUND_ID>00026</RETAIL_FUND_ID>
    <RETAIL_FUND_NAME>Pizza Fund</RETAIL_FUND_NAME>
    <RETAIL_FUND_SASID>00026</RETAIL_FUND_SASID>
    <TRADE_SYMBOL>CCHCC</TRADE_SYMBOL>
  </FUND_DATA>
</FUNDDATA>

Solution

  • This is just one of the nasties that you may find when using XML::Simple.

    In this case there is a solution: You need to enable the ForceArray option in the constructor call, like so

    my $xmltemp = XML::Simple->new(
        SuppressEmpty => 1,
        ForceArray    => 1,
    );
    

    The documentation has this to say about it

    This option should be set to '1' to force nested elements to be represented as arrays even when there is only one.