tags:

views:

439

answers:

2

I'm trying to write a simple SOAP client using SOAP::Lite. After making a request, the response only seems to be parsed into perl data structure a couple levels down. After that it's just a string of the remaining XML. I feel like it would be really kludgy to take that string and parse it manually with another XML parser.

my $response = $soap->getVersionInfo;    
my $data = $response->dataof('//getVersionInfoResponse');

The SOAP response looks like this in the SOAP::Lite trace:

<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"&gt;
   <soapenv:Body>
      <ns:getVersionInfoResponse xmlns:ns="http://webservice.jchem.chemaxon"&gt;
         <ns:return>
            &lt;Info>
            &lt;JChem>
            &lt;Version>5.2.6&lt;/Version>
            &lt;/JChem>
            &lt;Java>
            &lt;Vendor>Sun Microsystems Inc.&lt;/Vendor>
            &lt;VmName>Java HotSpot(TM) Client VM&lt;/VmName>
            &lt;Version>1.6.0_05&lt;/Version>
            &lt;/Java>
            &lt;Os>
            &lt;Arch>x86&lt;/Arch>
            &lt;Name>Windows XP&lt;/Name>
            &lt;Version>5.1&lt;/Version>
            &lt;/Os>
            &lt;/Info>
         </ns:return>
      </ns:getVersionInfoResponse>
   </soapenv:Body>
</soapenv:Envelope>

But what gets parsed into $data looks like this (from Data::Dumper::Concise):

\bless( {
    _attr => {},
    _name => "getVersionInfoResponse",
    _prefix => "ns",
    _signature => [],
    _uri => "http://webservice.jchem.chemaxon",
    _value => [
      {
        return => "<Info>\n<JChem>\n<Version>5.2.6</Version>\n</JChem>\n<Java>\n<Vendor>Sun Microsystems Inc.</Vendor>\n<VmName>Java HotSpot(TM) Client VM</VmName>\n<Version>1.6.0_05</Version>\n</Java>\n<Os>\n<Arch>x86</Arch>\n<Name>Windows XP</Name>\n<Version>5.1</Version>\n</Os>\n</Info>\n"
      }
    ]
  }, 'SOAP::Data' )

This is a simple example, but for more complex responses, it could become a huge hassle to have to parse out that XML.

I found this post on the SOAP::Lite mailing list (from 2003!) that had a worrisome quote on it:

Keep in mind the requirement that any attributes not natively known to SOAP must be namespace-qualified.

And I noticed that everything that wasn't getting parsed was not namespaced. Is there a way to force SOAP::Lite to parse that non-namespaced xml? Is that even the problem?

UPDATE:
It turns out SOAP::Lite was Doing The Right Thing. I'd overlooked a note in the service docs that that said

Note: The special characters inside <ns:return> tag are encoded to entities. (e.g. an xml return value will contain < characters, which will be encoded to &lt; entities) Therefore entity decoding is needed on the client side.

What I thought was just a trace output inconsistency was actually the problem. SOAP::Lite being nice and unescaping the entities before they ended up in the Dumper confused me as well. I originally included the documentation's example because it was already formatted nicely. Now the actual output is shown. Plus, everyone knows &lt; is the same as <, right? Right? ;_;

As of now I'm parsing the string with XML::LibXML, so the question still stands. Can I force SOAP::Lite to parse that interior XML string, even though it's been escaped?

+3  A: 

Works fine for me; $response->result gives the Info element with all children:

{
  Info => {
    JChem => {
      Version => "5.2.1"
    },
    Java => {
      Vendor => "Sun Microsystems Inc.",
      Version => "1.6.0_06",
      VmName => "Java HotSpot(TM) Server VM"
    },
    Os => {
      Arch => "x86",
      Name => "Windows XP",
      Version => "5.1"
    }
  }
}

And $response->dataof('//getVersionInfoResponse') returns a full-depth tree.

What version of Soap::Lite are you running? I'm using 0.710.10:

$sudo perl -MCPAN -e shell
cpan[6]> i SOAP:Lite
    ...
    INST_VERSION 0.710.10
Andomar
Thanks for answering. Your response made me question my premises. I've updated the question. And that hash structure is exactly what I want! XML::LibXML's format is much more obtuse. Any ideas on how I can get SOAP::Lite to parse that escaped xml?FWIW, I'm running 0.710.08, the newest in the Win32-Trouchelle repo.
wes
A: 

From what I learned on the SOAP::Lite mailing list (post), SOAP::Lite's intention is to only handle the protocol and envelope, not the interior of the message. I ended up using XML::Simple to parse the content of the response.

wes