1package SOAP::XML::Client::Generic; 2$SOAP::XML::Client::Generic::VERSION = '2.8'; 3use strict; 4use Carp; 5 6use base qw(SOAP::XML::Client); 7 8# Actually do the call 9sub _call { 10 my ( $self, $method ) = @_; 11 12 my @params = ( $self->{sdb}->to_soap_data() ); 13 unshift( @params, $self->header() ) if $self->header(); 14 15 my $caller 16 = $self->{soap}->uri( $self->uri() ) 17 ->proxy( $self->proxy(), timeout => $self->timeout() ) 18 ->soapversion( $self->soapversion() )->encoding( $self->encoding ); 19 20 my $res = $caller->$method(@params); 21 return $res, $caller->transport; 22} 23 241; 25__END__ 26 27=head1 NAME 28 29SOAP::XML::Client::Generic - talk with 'generic' webservices, e.g. not .net 30 31=head1 DESCRIPTION 32 33This package helps in talking with SOAP webservers, it just needs 34a bit of XML thrown at it and you get some XML back. 35It's designed to be REALLY simple to use, it doesn't try to 36be cleaver in any way (patches for 'cleaverness' welcome). 37 38The major difference to SOAP::XML::Client::DotNet is it will submit as: 39 40SOAPAction: "http://www.yourdomain.com/services#GetSellerActivity" 41 42and namesp<X> will be added to the XML submitted, including for 43the xmlns. 44 45=head1 SYNOPSIS 46 47 If your service looks like this: 48 49 <?xml version="1.0" encoding="utf-8"?> 50 <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> 51 <soap:Body> 52 <GetActivity xmlns="http://www.yourdomain.com/services"> 53 <userId>long</userId> 54 </GetActivity> 55 </soap:Body> 56 </soap:Envelope> 57 58 59 # Create an object with basic SOAP::Lite config stuff 60 my $soap_client = SOAP::XML::Client::Generic->new({ 61 uri => 'http://www.yourdomain.com/services', 62 proxy => 'http://www.yourproxy.com/services', 63 xmlns => 'http://www.yourdomain.com/services', 64 soapversion => '1.1', # defaults to 1.1 65 timeout => '30', # detauls to 30 seconds 66 strip_default_xmlns => 1, # defaults to 1 67 }); 68 69 70 # Create the following XML: 71 72 my $user_id = '900109'; 73 my $xml = "<userId _value_type='long'>$user_id</userId>"; 74 75 ########### 76 # Warning: you might have to supply data types (using _value_type) 77 # for each field, depending on the service you are talking to 78 ########### 79 80 # Actually do the call 81 if( $soap_client->fetch({ 82 'method' => 'GetActivity', 83 'xml' => $xml, 84 }) ) { 85 # Get result as a string 86 my $xml_string = $soap_client->result(); 87 88 # Get result as a XML::LibXML object 89 my $xml_libxml_object = $soap_client->result_xml(); 90 91 } else { 92 # Got an error 93 print "Problem using service:" . $soap_client->error(); 94 95 } 96 97=head1 methods 98 99=head2 new() 100 101 my $soap_client = SOAP::XML::Client::Generic->new({ 102 uri => 'http://www.yourdomain.com/services', 103 proxy => 'http://www.yourproxy.com/services', 104 xmlns => 'http://www.yourdomain.com/services', 105 soapversion => '1.1', # defaults to 1.1 106 timeout => '30', # detauls to 30 seconds 107 strip_default_xmlns => 1, # defaults to 1 108 }); 109 110This constructor requires uri, proxy and xmlns to be 111supplied, otherwise it will croak. 112 113strip_default_xmlns is used to remove xmlns="http://.../" 114from returned XML, it will NOT alter xmlns:FOO="http//.../" 115set to '0' if you do not wish for this to happen. 116 117=head2 header() 118 119 my $header = SOAP::Header->name( 120 SomeDomain => { 121 Username => "a_user", 122 Password => 'xxxxx', 123 } 124 )->uri('http://www.thedomain.com/')->prefix(''); 125 126 $soap_client->header($header); 127 128Add a soap header to the soap call, probably useful if there is 129credential based authenditcation 130 131=head2 fetch() 132 133 # Generate the required XML (you don't need the SOAP wrapper or method part of the XML 134 my $user_id = '900109'; 135 my $xml = "<userId _value_type='long'>$user_id</userId>"; 136 137 if($soap_client->fetch({ method => 'GetActivity', xml => $xml }) { 138 # Get result as a string 139 my $xml_string = $soap_client->result(); 140 141 # Get result as a XML::LibXML object 142 my $xml_libxml_object = $soap_client->result_xml(); 143 144 } else { 145 # There was some sort of error 146 print $soap_client->error() . "\n"; 147 } 148 149This method actually calls the web service, it takes a method name 150and an xml string. If there is a problem with either the XML or 151the SOAP transport (e.g. web server error/could not connect etc) 152undef will be returned and the error() will be set. 153 154Each node in the XML supplied (either by string or from a filename) 155can have _value_type defined or the submitted format may 156default to 'string' (depending on SOAP::Data::Builder). 157 158You can supply 'filename' rather than 'xml' and it will read in from 159the file. 160 161We check for Fault/faultstring in the returned XML, 162anything else you'll need to check for yourself. 163 164 165=cut 166 167=head2 error() 168 169 $soap_client->error(); 170 171If fetch returns undef then check this method, it will either be that the filename you 172supplied couldn't be read, the XML you supplied was not correctly formatted (XML::LibXML 173could not parse it), there was a transport error with the web service or Fault/faultstring 174was found in the XML returned. 175 176=head2 results(); 177 178 my $results = $soap_client->results(); 179 180Can be called after fetch() to get the raw XML, if fetch was sucessful. 181 182=head2 results_xml(); 183 184 my $results_as_xml = $soap_client->results_xml(); 185 186Can be called after fetch() to get the XML::LibXML Document element of the returned 187xml, as long as fetch was sucessful. 188 189=cut 190 191=head1 HOW TO DEBUG 192 193At the top of your script, before 'use SOAP::XML::Client::Generic' add: 194 195use SOAP::Lite ( +trace => 'all', 196 readable => 1, 197 outputxml => 1, 198 ); 199 200It may or may not help, not all services don't give you helpful error messages! 201At least you can see what's being submitted and returned. It can be the 202smallest thing that causes a problem, mis-typed data (see _value_type in xml), 203or typo in xmlns line. 204 205=head1 BUGS 206 207This is only designed to work with generic services, it may work 208 with others. I haven't found any open webservices which I can use 209to test against, but as far as I'm aware it all works - web services 210are all standard.. right.. :) ? 211 212=head1 AUTHOR 213 214Leo Lapworth <LLAP@cuckoo.org> 215 216=head1 COPYRIGHT 217 218(c) 2005 Leo Lapworth 219 220This library is free software, you can use it under the same 221terms as perl itself. 222 223=head1 SEE ALSO 224 225 <SOAP::XML::Client::DotNet>, <SOAP::XML::Client> 226 227=cut 228 2291; 230