Vemos y explicamos algunos ejemplos del uso de NuSOAP.
Para responder a esta pregunta no hay nada mejor que un ejemplo de utilización de NuSOAP, el cual nos ayudará también a terminar de ver los conceptos mencionados anteriormente (SOAP, WSDL, etc.).
Decidí ir a la página de XMethods y buscar algún servicio que pueda ser aplicable por personas de todo el mundo, y que no esté limitado a los Estados Unidos. Buscando entre gran cantidad de Web Services de Cotizaciones, o datos específicos de los Estados Unidos, encontré uno que podía ser implementado en cualquier país, y era ni más ni menos que los datos del clima para todo el mundo. Este Web Service tiene 9 métodos que podemos utilizar (todos ellos se encuentran definidos en el archivo WSDL que se encuentra en http://live.capescience.com/wsdl/GlobalWeather.wsdl. Los métodos son: getStation(), isValidCode(), listCountries(), searchByCode(), searchByCountry(), searchByLocation(), searchByName(), searchByRegion(), getWeatherReport().
Para el ejemplo solo utilizare el método searchByCountry() y getWeatherReport().
En el ejemplo existen dos archivos:
seleccionarLocalidad.php: el cual nos permitirá seleccionar una localidad dado un país (el país esta dado por el valor de la variable $sPais). Este archivo PHP utiliza el método del Web Service searchByCountry()
mostrarPronostico.php: el cual mostrara el pronóstico para la localidad seleccionada. Este archivo PHP utiliza el método del Web Service getWeatherReport().
Si queremos ver un listado de los servicios publicados podemos ir a esta página: CapeScience
En esta página nos permiten probar los métodos de los Web Services en línea, sin necesidad de un cliente SOAP, esto nos es de utilidad principalmente para ver como funciona cada uno de los métodos.
Como mencione anteriormente, toda la información del Web Service se encuentra definida dentro del documento WSDL, para este Web service se encuentra definida en CapeScience.
Este documento en particular tiene 425 líneas, por lo que la lectura del mismo es bastante tediosa.
No voy a explicar todo el archivo WSDL, sino que simplemente me detendré en las líneas que son de importancia para nuestra aplicación (las que hacen referencia a los metodos searchByCountry() y getWeatherReport() ). Ahora veamos donde se encuentran las definiciones de los métodos dentro del archivo:
Mensajes de searchByCountry: entre las lineas 277 a 282 podemos apreciar que se encuentra lo siguiente:
277. <message name="searchByCountryResponse">
278. <part name="return" type="xsd1:ArrayOfStation"/>
279. </message>
280. <message name="searchByCountry">
281. <part name="country" type="xsd:string"/>
282. </message>
SearchByCountry: comencemos por la línea 280 y dejaremos para después las líneas 277 a 279.
280. <message name="searchByCountry">
En esta línea se indica que existe un método llamado searchByCountry, que es el método que estábamos buscando.
281. <part name="country" type="xsd:string"/>
Aquí se define que existe un parámetro para dicho método que se llama country (país) y es del tipo string.
282. </message>
Fin del método seachByCountry
Ejemplo de un mensaje real con el parámetro country seteado en argentina:
<nu:searchByCountry>
<country xsi:type="xsd:string">argentina</country>
</nu:searchByCountry>
SearchByCountryResponse: Ahora analicemos el método searchByCountryResponse, como su nombre indica, es la respuesta al metodo searchByCountry. Es decir cuando invocamos a searchByCountry, el servidor nos responderá con un mensaje con el formato de searchByCountryResponse. Las respuestas, generalmente, tienen anexado al final Response al nombre del método (esto se epecifica en el portType).
277. <message name="searchByCountryResponse">
Esta línea nos indica que es una respuesta al método searchByCountry.
278. <part name="return" type="xsd1:ArrayOfStation"/>
El método nos devuelve una variable return la cual es del tipo ArrayOfSation. Como vimos anteriormente, los documentos WSDL pueden definir sus propios tipos de datos, ArrayOfStation es un tipo de datos definido en este WSDL. Ver más adelante la definición del tipo de datos ArrayOfStation.
279. </message>
Fin del método searchByCountryResponse.
Como vimos anteriormente se hace referencia a un ArrayOfStation, para ver de que se trata esto debemos buscar este tipo de datos dentro del archivo WSDL. En las líneas comprendidas ente 148 y 157, podemos ver que se define este tipo de datos.
148. <xsd:complexType name="ArrayOfStation">
149. <xsd:complexContent>
150. <xsd:restriction base="SOAP-ENC:Array">
151. <xsd:sequence>
152. <xsd:element maxOccurs="unbounded" minOccurs="0" name="item" type="xsd1:Station"/>
153. </xsd:sequence>
154. <xsd:attribute ref="SOAP-ENC:arrayType" wsdl:arrayType="xsd1:Station[]"/>
155. </xsd:restriction>
156. </xsd:complexContent>
157. </xsd:complexType>
148. <xsd:complexType name="ArrayOfStation">
En esta línea podemos ver que se define un tipo de datos complejo (complexType) con el nombre de ArrayOfStation, el tipo de datos que buscábamos.
149. <xsd:complexContent>
150. <xsd:restriction base="SOAP-ENC:Array">
151. <xsd:sequence>
Indicamos que es un elemento complejo (array).
152. <xsd:element maxOccurs="unbounded" minOccurs="0" name="item" type="xsd1:Station"/>
Esta línea es la que más nos interesa, ya que se indica precisamente como esta compuesto el array. Nos dice que tiene un mínimo de ocurrencias de 0 (MinOccurs= 0 ), es decir, que puede no tener elementos. Un máximo de ocurrencias no limitado (maxOccurs=unbounded), es decir que podemos tener todos los elementos que queramos. Y al finalizar nos indica el tipo de datos del array, que es Station. Por desgracia ahora tenemos que ver que tipo de datos es Station. Como podemos ver un dato se define a partir de otro, hasta llegar a los tipos de datos básicos.
153. </xsd:sequence>
Se cierran los tags anteriormente abiertos.
154. <xsd:attribute ref="SOAP-ENC:arrayType" wsdl:arrayType="xsd1:Station[]"/>
Terminamos de definir el array.
155. </xsd:restriction>
156. </xsd:complexContent>
157. </xsd:complexType>
Se cierran los demás tags que fueron abiertos.
Nos quedaba pendiente definir el tipo de datos Station, nuevamente, al buscar en el código encontramos entre las líneas 134 a 147 la definición de este tipo de datos.
134. <xsd:complexType name="Station">
135. <xsd:sequence>
136. <xsd:element maxOccurs="1" minOccurs="1" name="icao" nillable="true" type="xsd:string"/>
137. < xsd:element maxOccurs="1" minOccurs="1" name="wmo" nillable="true" type="xsd:string"/>
138. < xsd:element maxOccurs="1" minOccurs="1" name="iata" nillable="true" type="xsd:string"/>
139. < xsd:element maxOccurs="1" minOccurs="1" name="elevation" type="xsd:double"/>
140. < xsd:element maxOccurs="1" minOccurs="1" name="latitude" type="xsd:double"/>
141. < xsd:element maxOccurs="1" minOccurs="1" name="longitude" type="xsd:double"/>
142. < xsd:element maxOccurs="1" minOccurs="1" name="name" nillable="true" type="xsd:string"/>
143. < xsd:element maxOccurs="1" minOccurs="1" name="region" nillable="true" type="xsd:string"/>
144. < xsd:element maxOccurs="1" minOccurs="1" name="country" nillable="true" type="xsd:string"/>
145. <xsd:element maxOccurs="1" minOccurs="1" name="string" nillable="true" type="xsd:string"/>
146. </xsd:sequence>
147. </xsd:complexType>
134. <xsd:complexType name="Station">
Se define que comienza el tipo de datos complejo Station.
135. <xsd:sequence>
Indicamos que comenzamos con la definición del tipo secuencia (es decir que todos los elementos que se definen dentro están incluidos en el tipo de datos Station). Existen otro tipo que no es secuencia (sequence), y se llama choice (elección), en el cual se selecciona entre uno de los elementos dentro definidos (aquellos comprendidos entre <xsd:choice>y </xsd:choice>).
136. <xsd:element maxOccurs="1" minOccurs="1" name="icao" nillable="true" type="xsd:string"/>
137. <xsd:element maxOccurs="1" minOccurs="1" name="wmo" nillable="true" type="xsd:string"/>
138. <xsd:element maxOccurs="1" minOccurs="1" name="iata" nillable="true" type="xsd:string"/>
Se definen 3 elementos los cuales son del tipo string, dichos elementos son: icao, wmo, e iata.
139. <xsd:element maxOccurs="1" minOccurs="1" name="elevation" type="xsd:double"/>
140. <xsd:element maxOccurs="1" minOccurs="1" name="latitude" type="xsd:double"/>
141. <xsd:element maxOccurs="1" minOccurs="1" name="longitude" type="xsd:double"/>
Se definen otros 3 elementos, en este caso son del tipo double. Estos son: elevation, latitude, y longitude.
142. <xsd:element maxOccurs="1" minOccurs="1" name="name" nillable="true" type="xsd:string"/>
143. <xsd:element maxOccurs="1" minOccurs="1" name="region" nillable="true" type="xsd:string"/>
144. <xsd:element maxOccurs="1" minOccurs="1" name="country" nillable="true" type="xsd:string"/>
145. <xsd:element maxOccurs="1" minOccurs="1" name="string" nillable="true" type="xsd:string"/>
Se definen los últimos 4 elementos del tipo string. Los elementos aquí definidos son: name, region, country, y string.
146. </xsd:sequence>
147. </xsd:complexType>
Cierre de los tags abiertos anteriormente.
Veamos un ejemplo de respuesta:
<return xsi:type="cc1:ArrayOfStation" SOAP-ENC:arrayType="cc1:Station[86]">
<item xsi:type="cc1:Station">
<icao xsi:type="xsd:string">SARS</icao>
<wmo xsi:type="xsd:string">87149</wmo>
<iata xsi:nil="true"/>
<elevation xsi:type="xsd:double">91.0</elevation>
<latitude xsi:type="xsd:double">-26.817</latitude>
<longitude xsi:type="xsd:double">-60.45</longitude>
<name xsi:type="xsd:string">Presidencia Roque Saenz Pena Aerodrome</name>
<region xsi:nil="true"/>
<country xsi:type="xsd:string">
Argentina </country>
<string xsi:type="xsd:string">SARS - Presidencia Roque Saenz Pena Aerodrome, Argentina
@ -26.817'S -60.45'W 91m</string>
</item>
<item xsi:type="cc1:Station">
</return>
Para aclarar el tipo de estructura de ArrayOfStation usaremos analogías con otros lenguajes de programación:
// Delphi //
Station = record
icao : String;
wmo : String;
iata : String;
elevation : String;
latitude : String;
longitude : String;
name : String;
region : String;
country : String;
string_ : String;
end;
ArrayOfSation : array of Station;
// C# //
struct Station
{
String icao;
String wmo;
String iata;
String elevation;
String latitude;
String longitude;
String name;
String region;
String country;
String string_;
}
Station[] ArrayOfStation;
Como vemos no es fácil seguir todo lo que esta definido dentro de un documento WSDL, por suerte muchas veces no nos tenemos que preocupar por todo esto ya que los mismos sitios donde se encuentran alojados los Web Services nos proveen de la información necesaria sin necesidad de tener que recurrir a ver los archivos WSDL. También existen aplicaciones como son Altova XMLSPY que nos proveen de la información de manera gráfica
Orlando Fabián Brea