¿Como lo usamos?
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