Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • I agree that SOAP::Lite is quite opaque.  In my work, I usually skip the "handy" wrappers that SOAP::Lite offers and dig into the XML.  Here's a snippet like what I use in my unreleased SOAPClient package

    sub call
    {
      my ($uri, $proxy, $timeout, $method, $args, $want) = @_;
      my @args = map {SOAP::Data->name($_, $args->{$_})} keys %$args;
      my $som = SOAP::Lite
         ->uri($uri)
         ->proxy($proxy, timeout => $timeout)
         ->call($method, @args);
      for (@$want) {
        my $wantArray = (s/^\@//);
        my @vals;
        if ($som->match("/Envelope/Body/[1]/$_")) {
           @vals = $som->valueof();
        push @rets, $wantArray ? [@vals], $vals[0];
      }
      return @rets;
    }

    Then use this like as follows (fictional service):

    my ($temp, $humid) = call($uri, $proxy, 30, "getWeather", {zip => 53711}, ["temp", "humidity]);

    This works best if the server looks like this:

    our @ISA = qw(SOAP::Server::Parameters);
    sub getWeather
    {
      my %data;
      if ($_[-1] && UNIVERSAL::isa($_[-1] => 'SOAP::SOM') {
        %data = %{$_[-1]->method() || {}};
      } else {
        push @_, undef if (@_ %2 != 0);  # need even number of elements
        %data = @_;
      }
      if (!$data{zip}) {
         die SOAP::Fault->faultcode("MissingData")->faultstring("Zip not provided");
      }
      my ($temp, $windspeed, $humidity) = weather($data{zip});
      return SOAP::Data->name(temperature => $temp),
             SOAP::Data->name(windspeed => $wind),
             SOAP::Data->name(humidity => $humidity);
    }

    That server can be specified by the following WSDL (which is
    incomplete since it lacks a service tag):

    <?xml version="1.0" encoding="UTF-8" standalone="no" ?>
    <definitions targetNamespace="urn:Weather" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="urn:Weather" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <documentation>
        Partial WSDL auto-generated from soap.pod by /perl/bin/pod2wsdl
      </documentation>
      <message name="getWeatherRequest">
        <part name="zip" type="xsd:integer"/>
      </message>
      <message name="getWeatherResponse">
        <part name="temperature" type="xsd:float"/>
        <part name="windspeed" type="xsd:float"/>
        <part name="humidity" type="xsd:float"/>
      </message>
      <portType name="WeatherInterface">
        <operation name="getWeather">
          <input message="tns:getWeatherRequest"/>
          <output message="tns:getWeatherResponse"/>
        </operation>
      </portType>
      <binding name="WeatherBinding" type="tns:WeatherInterface">
        <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
        <operation name="getWeather">
          <soap:operation soapAction="http://weather.foo.com/Weather#getWeather"/>
          <input>
            <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://weather.foo.com/Weather" use="encoded"/>
          </input>
          <output>
            <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://weather.foo.com/Weather" use="encoded"/>
          </output>
        </operation>
      </binding>
    </definitions>