Question

I have an XML string, which I parse using LibXML's findnodes & textContent, and this works well:

#!/usr/bin/perl -w

use strict;
use warnings;

use SOAP::Lite 0.715;
use Data::Dumper;
use XML::LibXML qw();

my $cust_xml  = '<?xml version="1.0" standalone="yes"?>
<CUSTOMER_RESPONSE>
  <CUSTOMER>
    <TEL>555-555-5555</TEL>
  </CUSTOMER>
  <PRODUCTS>
    <PRODUCT>
      <PRODUCT_ID>Apple</PRODUCT_ID>
    </PRODUCT>
    <PRODUCT>
      <PRODUCT_ID>BlackBerry</PRODUCT_ID>
    </PRODUCT>
    <PRODUCT>
      <PRODUCT_ID>Orange</PRODUCT_ID>
    </PRODUCT>
  </PRODUCTS>
</CUSTOMER_RESPONSE>
';

my $dom = XML::LibXML->load_xml(string => $cust_xml);
for my $productNode ($dom->findnodes('//PRODUCT_ID')) {
    my $product_id = $productNode->textContent;
    print STDERR "id=$product_id\n";
}

My target machine (Perl 5.8.8 on HP-UX), however, does not contain XML::LibXML and I was hoping I could achieve the same using SOAP::SOM. However, I can't seem to get the correct syntax:

my $som = SOAP::SOM->new($cust_xml);
for my $productNode ($som->valueof('//PRODUCTS/PRODUCT')) {
    my $product_id = $productNode->{'PRODUCT_ID'};
    print STDERR "id=$product_id\n";
}

When I run the code snippet above, I get a run-time error:

% ./som.pl
Can't use string ("<?xml version="1.0" standalone=""...) as an ARRAY ref while "strict refs" in use at /Users/<username>/perl5/lib/perl5/SOAP/Lite.pm line 391.

Do you have any suggestions, or even recommend another generic library which is likely to be found on older machines?

-hq

Was it helpful?

Solution

This is a very odd approach to parsing XML. Is there no other effective XML module that you can use, such as XML::Twig?

SOAP::SOM expects something more than bare XML in the parameter to its constructor. It is normally created by accessing a remote SOAP server using SOAP::Lite.

You need to use SOM::Deserializer, like this

use strict;
use warnings;

use SOAP::Lite;

my $cust_xml  = <<'__END_XML__';
<CUSTOMER_RESPONSE>
  <CUSTOMER>
    <TEL>555-555-5555</TEL>
  </CUSTOMER>
  <PRODUCTS>
    <PRODUCT>
      <PRODUCT_ID>Apple</PRODUCT_ID>
    </PRODUCT>
    <PRODUCT>
      <PRODUCT_ID>BlackBerry</PRODUCT_ID>
    </PRODUCT>
    <PRODUCT>
      <PRODUCT_ID>Orange</PRODUCT_ID>
    </PRODUCT>
  </PRODUCTS>
</CUSTOMER_RESPONSE>
__END_XML__

my $som = SOAP::Deserializer->deserialize($cust_xml);

print "$_\n" for $som->valueof('//PRODUCT_ID');

output

Apple
BlackBerry
Orange
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top