I've been using perl to provide soap/wsdl services or be a soap client for a few years now. The SOAP::Lite package is truly a godsend for making soap easy.
However, I constantly run into one problem that I seem to need to resolve very few months. I'm documenting it here.
SOAP::Lite enjoys putting c-gensym/s-gensym tags around the arguments of my soap method and method response. generally perl figures out what I want when I'm using perl on both the server and client side. However when I have to conform to a standard or operate cross languages, these gensym tags cause problems.
Most frequently I have a hashref I want to return. I want the XML to look like this:
<element_1>
<value>a</value>
</element_1>
<element_2>
<value>b</value>
</element_2>
So my hashref looks like this:
$hash->{element_1}->{value} = a
$hash->{element_b}->{value} = b
But to create that XML, SOAP::Lite is looking for an array, and in particular an array of SOAP::DATA elements with name/value pairs of 'element_1' ↔ {value ⇒ 'a'} and 'element_2' ↔ {value ⇒ 'b'}.
It's easy to make the proper value using map and SOAP::Lite. Simply do this:
$send_this = SOAP::Data->value(
map
{ SOAP::Data->name( $_ => $hash->{$_}) }
keys(%{$hash})
);
Basically, this pulls each top-level hash element from $hash, turns the element into a SOAP::Data() name/value pair, pushes onto an array, and then SOAP:Data()'s that final result.
The result is suitable for sending to SOAP::Lite and getting a SOAP method body that looks as desired.
If your hashref is deeper than this example, no problem. SOAP::Lite handles that correctly. Only the top-level elements need to be converted to these SOAP::Data() name/value pairs. The hashrefs inside them translate to XML properly without further user intervention.
Discussion