http://www.perlmonks.org?node_id=995573

fritz1968 has asked for the wisdom of the Perl Monks concerning the following question:

I have (mostly) figured out soap::lite. However, I cannot tell anyone as it is a closely guarded secret. ;-)

I say mostly, as I want to generate a document that will have multiple request in it. Take the following code for example:

sub release { my ($args) = @_; # IIS web services expect / as a separator for uri and method. my $lite = SOAP::Lite->new()->on_action(sub { join '/', @_ } ) ->proxy($args->{proxy}), SOAP::Header->name('Authentication' => SOAP::Header->value( SOAP::Header->name('user')->value($zID), SOAP::Header->name('password')->value($zPW))) +; my $response = $lite->call( SOAP::Data->name('release') ->attr({ 'xmlns', $args->{xmlns}}), SOAP::Data->name('request' => \SOAP::Data->value( SOAP::Data->name('actionTime')->value($args->{actio +nTime}), SOAP::Data->name('id')->value($args->{id})->type('l +ong'), SOAP::Data->name('state')->value($args->{state})->t +ype('string'), SOAP::Data->name('result')->value($args->{result})- +>type('string') )), ); return $response; }

This will generate the following XML document:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envel +ope/" xmlns:ns="http://myid.somecompany.net/request/service/3"> <soapenv:Header/> <soapenv:Body> <ns:release> <ns:request> <ns:id>4161</ns:id> <ns:actionTime>2012-09-25T13:26:43.000Z</ns:actionTime> <ns:state>PLACED</ns:state> <ns:result>ACTION_TAKEN</ns:result> </ns:request> </ns:release> </soapenv:Body> </soapenv:Envelope>

My next task is to create an XML document that generated multiple "requests." For example, the following:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envel +ope/" xmlns:ns="http://myid.somecompany.net/request/service/3"> <soapenv:Header/> <soapenv:Body> <ns:release> <ns:request> <ns:id>4161</ns:id> <ns:actionTime>2012-09-25T13:26:43.000Z</ns:actionTime> <ns:state>PLACED</ns:state> <ns:result>ACTION_TAKEN</ns:result> </ns:request> <ns:request> <ns:id>4162</ns:id> <ns:actionTime>2012-09-25T13:26:44.000Z</ns:actionTime> <ns:state>PLACED</ns:state> <ns:result>ACTION_TAKEN</ns:result> </ns:request> </ns:release> </soapenv:Body> </soapenv:Envelope>

I know the magic has to happen in this section of the code:

my $response = $lite->call( SOAP::Data->name('release') ->attr({ 'xmlns', $args->{xmlns}}), SOAP::Data->name('request' => \SOAP::Data->value( SOAP::Data->name('actionTime')->value($args->{actio +nTime}), SOAP::Data->name('id')->value($args->{id})->type('l +ong'), SOAP::Data->name('state')->value($args->{state})->t +ype('string'), SOAP::Data->name('result')->value($args->{result})- +>type('string') )), );

but the question is how? a loop of some sort is, obviously, needed. But where to I put it? The variable that I am using to store the data is an array of hashes. In the above code, I am simply passing a single hash. However, I can always pass the array of hashes.

any help, suggestions, ideas would be appreciated. Thanks, Frank

Replies are listed 'Best First'.
Re: More Soap::Lite
by Anonymous Monk on Sep 25, 2012 at 20:22 UTC

    I have (mostly) figured out soap::lite. ... but the question is how? a loop of some sort is, obviously, needed. But where to I put it?

    #!/usr/bin/perl -- use SOAP::Lite; my $soap = SOAP::Lite->proxy( 'http://localhost/blah/DummyService', timeout => 0.00001, ); $soap->transport->add_handler("request_send", \&pp_dump ); my $serializer = $soap->serializer(); my @data = ( SOAP::Data->name( 'request' => \SOAP::Data->value( SOAP::Data->name('actionTime')->value('actionTime'), SOAP::Data->name('id')->value('id')->type('long'), SOAP::Data->name('state')->value('state')->type('string'), SOAP::Data->name('result')->value('result')->type('string' +) ) ), SOAP::Data->name( 'request' => \SOAP::Data->value( SOAP::Data->name('actionTime')->value('actionTime'), SOAP::Data->name('id')->value('id')->type('long'), SOAP::Data->name('state')->value('state')->type('string'), SOAP::Data->name('result')->value('result')->type('string' +) ) ), ); print pp( $serializer->envelope( method => SOAP::Data->name('release')->attr( { 'xmlns', 'ns' } + ), @data, ), ); $soap->call( SOAP::Data->name('release')->attr( { 'xmlns', 'ns' } ), @data, ); sub pp { use XML::Twig; open my($fh), '>', \my $str; no warnings 'newline'; XML::Twig->new( qw! pretty_print record ! )->parse( @_ )->print( $fh ); return $str; } sub pp_dump { { my $content = $_[0]->content(''); $_[0]->content( pp($content) ); } print $_[0]->as_string,"\n"; return; }

      Thanks for the code. I modeled my code after yours and came up with the following:

      foreach $rHash (@userData) { my $tempString = (); $tempString=SOAP::Data->name('request' => \SOAP::Data->value( SOAP::Data->name('actionTime')->value($zTime), SOAP::Data->name('id')->value($id1)->type('long'), SOAP::Data->name('state')->value($state1)->type('string'), SOAP::Data->name('result')->value($result1)->type('string') )); push(@soapArray, $tempString); }# end foreach my $release_response = release($proxy, $xmlns, @soapArray);

      Before the above code is executed, the user Data is retrieved from a WSDL and stored in an array - @userData - of hashes. That array of hashes is ran through a foreach loop to dynamically format each record to a string ($tempString) and then to add that string to an array (@soapArray). Then I call a subroutine and pass the necessary information to execute the WSDL call:
      my $release_response = release($proxy, $xmlns, @soapArray);

      In the subroutine, I make the WSDL call:

      my ($proxy1, $xmlns1, @array1) = @_; # IIS web services expect / as a separator for uri and method. my $lite = SOAP::Lite->new()->on_action(sub { join '/', @_ } ) ->proxy($proxy1), SOAP::Header->name('Authentication' => SOAP::Header->value( SOAP::Header->name('user')->value($zID), SOAP::Header->name('password')->value($zPW))); my $response = $lite->call( SOAP::Data->name('release') ->attr({ 'xmlns', $xmlns1}), @array1 ); return $response;

      The name of the array changes in the subroutine from @soapArray to @array1.

      Again, thanks for the help. It is much appreciated.
      Frank