1# ====================================================================== 2# 3# Copyright (C) 2000-2003 Paul Kulchenko (paulclinger@yahoo.com) 4# SOAP::Lite is free software; you can redistribute it 5# and/or modify it under the same terms as Perl itself. 6# 7# $Id: SOM.pm,v 1.1 2004/10/12 18:47:55 byrnereese Exp $ 8# 9# ====================================================================== 10 11=pod 12 13=head1 NAME 14 15SOAP::SOM - provides access to the values contained in SOAP Response 16 17=head1 DESCRIPTION 18 19Objects from the SOAP::SOM class aren't generally instantiated directly by an application. Rather, they are handed back by the deserialization of a message. In other words, developers will almost never do this: 20 21 $som = SOAP::SOM->new; 22 23SOAP::SOM objects are returned by a SOAP::Lite call in a client context. For example: 24 25 my $client = SOAP::Lite 26 ->readable(1) 27 ->uri($NS) 28 ->proxy($HOST) 29 $som = $client->someMethod(); 30 31=head1 METHODS 32 33=over 34 35=item new(message) 36 37 $som = SOAP::SOM->new($message_as_xml); 38 39As said, the need to actually create an object of this class should be very rare. However, if the need arises, the syntax must be followed. The single argument to new must be a valid XML document the parser will understand as a SOAP response. 40 41=back 42 43The following group of methods provide general data retrieval from the SOAP::SOM object. The model for this is an abbreviated form of XPath. Following this group are methods that are geared towards specific retrieval of commonly requested elements. 44 45=over 46 47=item match(path) 48 49 $som->match('/Envelope/Body/[1]'); 50 51This method sets the internal pointers within the data structure so that the retrieval methods that follow will have access to the desired data. In the example path, the match is being made against the method entity, which is the first child tag of the body in a SOAP response. The enumeration of container children starts at 1 in this syntax, not 0. The returned value is dependent on the context of the call. If the call is made in a boolean context (such as C<< if ($som->match($path)) >>), the return value is a boolean indicating whether the requested path matched at all. Otherwise, an object reference is returned. The returned object is also a SOAP::SOM instance but is smaller, containing the subset of the document tree matched by the expression. 52 53=item valueof(node) 54 55 $res = $som->valueof('[1]'); 56 57When the SOAP::SOM object has matched a path internally with the match method, this method allows retrieval of the data within any of the matched nodes. The data comes back as native Perl data, not a class instance (see dataof). In a scalar context, this method returns just the first element from a matched node set. In an array context, all elements are returned. Assuming that the earlier call happens after the earlier call to match, it retrieves the result entity from the method response that is contained in C<$som>, as this is the first child element in a method-response tag. 58 59=item dataof(node) 60 61 $resobj = $som->dataof('[1]'); 62 63Performs the same operation as the earlier valueof method, except that the data is left in its L<SOAP::Data> form, rather than being deserialized. This allows full access to all the attributes that were serialized along with the data, such as namespace and encoding. 64 65=item headerof(node) 66 67 $resobj = $som->headerof('[1]'); 68 69Acts much like dataof, except that it returns an object of the L<SOAP::Header> class (covered later in this chapter), rather than SOAP::Data. This is the preferred interface for manipulating the header entities in a message. 70 71=item namespaceuriof(node) 72 73 $ns = $som->namespaceof('[1]'); 74 75Retrieves the namespace URI that governs the requested node. Note that namespaces are inherited, so this method will return the relevant value, even if it derives from a parent or other ancestor node. 76 77=back 78 79The following methods provide more direct access to the message envelope. All these methods return some form of a Perl value, most often a hash reference, when called. Context is also relevant: in a scalar context only the first matching node is returned, while in an array context, all matching nodes are. When called as a static method or as a regular function (such as C<SOAP::SOM::envelope>), any of the following methods returns the XPath string that is used with the match method to retrieve the data. 80 81=over 82 83=item root 84 85 $root = $som->root; 86 87Returns the value of the root element as a hash reference. It behaves exactly as C<$som->valueof('/')> does. 88 89=item envelope 90 91 $envelope = $som->envelope; 92 93Retrieves the "Envelope" element of the message, returning it and its data as a hash reference. Keys in the hash will be Header and Body (plus any optional elements that may be present in a SOAP 1.1 envelope), whose values will be the serialized header and body, respectively. 94 95=item header 96 97 $header = $som->header; 98 99Retrieves the header portion of the envelope as a hash reference. All data within it will have been deserialized. If the attributes of the header are desired, the static form of the method can be combined with match to fetch the header as a SOAP::Data object: 100 101 $header = $som->match(SOAP::SOM::header)->dataof; 102 103=item headers 104 105 @hdrs = $som->headers; 106 107Retrieves the node set of values with deserialized headers from within the Header container. This is different from the earlier header method in that it returns the whole header as a single structure, and this returns the child elements as an array. In other words, the following expressions yield the same data structure: 108 109 $header = ($som->headers)[0]; 110 $header = $som->valueof(SOAP::SOM::header.'/[1]'); 111 112=item body 113 114 $body = $som->body; 115 116Retrieves the message body as a hash reference. The entity tags act as keys, with their deserialized content providing the values. 117 118=item fault 119 120 if ($som->fault) { die $som->fault->faultstring } 121 122Acts both as a boolean test whether a fault occurred, and as a way to retrieve the Fault entity itself from the message body as a hash reference. If the message contains a fault, the next four methods (faultcode, faultstring, faultactor, and faultdetail) may be used to retrieve the respective parts of the fault (which are also available on the hash reference as keys). If fault in a boolean context is true, the C<result>, C<paramsin>, C<paramsout>, and C<method> methods all return C<undef>. 123 124=item faultcode 125 126 $code = $som->faultcode; 127 128Returns the faultcode element of the fault if there is a fault; undef otherwise. 129 130=item faultstring 131 132 $string = $som->faultstring; 133 134Returns the faultstring element of the fault if there is a fault; undef otherwise. 135 136=item faultactor 137 138 $actor = $som->faultactor; 139 140Returns the faultactor element of the fault, if there is a fault and if the actor was specified within it. The faultactor element is optional in the serialization of a fault, so it may not always be present. This element is usually a string. 141 142=item faultdetail 143 144 $detail = $som->faultdetail; 145 146Returns the content of the detail element of the fault, if there is a fault and if the detail element was provided. Note that the name of the element isn't the same as the method, due to the possibility for confusion had the method been called simply, detail. As with the faultactor element, this isn't always a required component of a fault, so it isn't guaranteed to be present. The specification for the detail portion of a fault calls for it to contain a series of element tags, so the application may expect a hash reference as a return value when detail information is available (and undef otherwise). 147 148=item method 149 150 $method = $som->method 151 152Retrieves the "method" element of the message, as a hash reference. This includes all input parameters when called on a request message or all result/output parameters when called on a response message. If there is a fault present in the message, it returns undef. 153 154=item result 155 156 $value = $som->result; 157 158Returns the value that is the result of a SOAP response. The value will be already deserialized into a native Perl datatype. 159 160=item paramsin 161 162 @list = $som->paramsin; 163 164Retrieves the parameters being passed in on a SOAP request. If called in a scalar context, the first parameter is returned. When called in a list context, the full list of all parameters is returned. Each parameter is a hash reference, following the established structure for such return values. 165 166=item paramsout 167 168 @list = $som->paramsout; 169 170Returns the output parameters from a SOAP response. These are the named parameters that are returned in addition to the explicit response entity itself. It shares the same scalar/list context behavior as the paramsin method. 171 172=item paramsall 173 174 @list = $som->paramsall; 175 176Returns all parameters from a SOAP response, including the result entity itself, as one array. 177 178=item parts() 179 180Return an array of C<MIME::Entity>'s if the current payload contains attachments, or returns undefined if payload is not MIME multipart. 181 182=item is_multipart() 183 184Returns true if payload is MIME multipart, false otherwise. 185 186=back 187 188=head1 EXAMPLES 189 190=head2 ACCESSING ELEMENT VALUES 191 192Suppose for the following SOAP Envelope: 193 194 <Envelope> 195 <Body> 196 <fooResponse> 197 <bar>abcd</bar> 198 </fooResponse> 199 </Body> 200 </Envelope> 201 202And suppose you wanted to access the value of the bar element, then use the following code: 203 204 my $soap = SOAP::Lite 205 ->uri($SOME_NS) 206 ->proxy($SOME_HOST); 207 my $som = $soap->foo(); 208 print $som->valueof('//fooResponse/bar'); 209 210=head2 ACCESSING ATTRIBUTE VALUES 211 212Suppose the following SOAP Envelope: 213 214 <Envelope> 215 <Body> 216 <c2fResponse> 217 <convertedTemp test="foo">98.6</convertedTemp> 218 </c2fResponse> 219 </Body> 220 </Envelope> 221 222Then to print the attribute 'test' use the following code: 223 224 print "The attribute is: " . 225 $som->dataof('//c2fResponse/convertedTemp')->attr->{'test'}; 226 227=head2 ITERATING OVER AN ARRAY 228 229Suppose for the following SOAP Envelope: 230 231 <Envelope> 232 <Body> 233 <catalog> 234 <product> 235 <title>Programming Web Service with Perl</title> 236 <price>$29.95</price> 237 </product> 238 <product> 239 <title>Perl Cookbook</title> 240 <price>$49.95</price> 241 </product> 242 </catalog> 243 </Body> 244 </Envelope> 245 246If the SOAP Envelope returned contained an array, use the following code to iterate over the array: 247 248 for my $t ($som->valueof('//catalog/product')) { 249 print $t->{title} . " - " . $t->{price} . "\n"; 250 } 251 252=head2 DETECTING A SOAP FAULT 253 254A SOAP::SOM object is returned by a SOAP::Lite client regardless of whether the call succeeded or not. Therefore, a SOAP Client is responsible for determining if the returned value is a fault or not. To do so, use the fault() method which returns 1 if the SOAP::SOM object is a fault and 0 otherwise. 255 256 my $som = $client->someMethod(@parameters); 257 258 if ($som->fault) { 259 print $som->faultdetail; 260 } else { 261 # do something 262 } 263 264=head2 PARSING ARRAYS OF ARRAYS 265 266The most efficient way To parse and to extract data out of an array containing another array encoded in a SOAP::SOM object is the following: 267 268 $xml = <<END_XML; 269 <foo> 270 <person> 271 <foo>123</foo> 272 <foo>456</foo> 273 </person> 274 <person> 275 <foo>789</foo> 276 <foo>012</foo> 277 </person> 278 </foo> 279 END_XML 280 281 my $som = SOAP::Deserializer->deserialize($xml); 282 my $i = 0; 283 foreach my $a ($som->dataof("//person/*")) { 284 $i++; 285 my $j = 0; 286 foreach my $b ($som->dataof("//person/[$i]/*")) { 287 $j++; 288 # do something 289 } 290 } 291 292=head1 SEE ALSO 293 294L<SOAP::Data>, L<SOAP::Serializer> 295 296=head1 ACKNOWLEDGEMENTS 297 298Special thanks to O'Reilly publishing which has graciously allowed SOAP::Lite to republish and redistribute large excerpts from I<Programming Web Services with Perl>, mainly the SOAP::Lite reference found in Appendix B. 299 300=head1 COPYRIGHT 301 302Copyright (C) 2000-2004 Paul Kulchenko. All rights reserved. 303 304This library is free software; you can redistribute it and/or modify 305it under the same terms as Perl itself. 306 307=head1 AUTHORS 308 309Paul Kulchenko (paulclinger@yahoo.com) 310 311Randy J. Ray (rjray@blackperl.com) 312 313Byrne Reese (byrne@majordojo.com) 314 315=cut 316