Extraer un XSD a partir de un XML existente

A veces me he encontrado en la tesitura de tener un XML maravilloso con toda la información que necesito y querer explotar su información mediante Java.

Si utilizamos JAXB, el estándar de Java para el tratamiento XML-JAVA, veremos que el compilador xjc, incluido en la JDK (a partir de la versión 1.6.0_3), necesita un XSD para generar los objetos java correspondientes.

Por tanto, el primer paso, y el motivo de esta entrada, es tratar las diferentes maneras que hay de convertir el XML en un XSD.

Voy a utilizar para la generación del XSD un XML de ejemplo sencillo, pero suficiente, para ver las diferencias entre las herramientas presentadas.

<?xml version="1.0" encoding="UTF-8"?>
<servers>
	<server id="svnserver.com">
		<ip>192.168.1.1</ip>
		<osuser>souser</osuser>
		<ospass>sopass</ospass>
		<repositories>
			<repository name="a53">
				<url>http://svnserver.com/svn/a53</url>
				<svnuser>user</svnuser>
				<svnpass>pass</svnpass>
			</repository>
			<repository name="i07">
				<url>http://svnserver.com/svn/i07</url>
				<svnuser>user</svnuser>
				<svnpass>pass</svnpass>
			</repository>
		</repositories>
	</server>
	<server id="svnserver2.com">
		<ip>192.168.1.2</ip>
		<osuser>souser</osuser>
		<ospass>sopass</ospass>
		<repositories>
			<repository name="a53_backup">
				<url>http://svnserver.com/svn/a53_backup</url>
				<svnuser>user</svnuser>
				<svnpass>pass</svnpass>
			</repository>
		</repositories>
	</server>
</servers>

Trang.jar (http://www.thaiopensource.com/relaxng/trang.html)

Este programa no se actualiza desde 2008, pero tampoco es preocupante porque tampoco ha cambiado la especificación W3C de los XML Schemas. Se puede descargar directamente desde su página web y es muy sencillo de utilizar.

usage: java -jar trang.jar 
		[-I rng|rnc|dtd|xml] 
		[-O rng|rnc|dtd|xsd] 
		[-i input-param] 
		[-o output-param] 
		inputFileOrUri ... outputFile

Partiendo del XML de ejemplo propuesto, la respuesta de trang ha sido la siguiente:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
  <xs:element name="servers">
    <xs:complexType>
      <xs:sequence>
        <xs:element maxOccurs="unbounded" ref="server"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="server">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="ip"/>
        <xs:element ref="osuser"/>
        <xs:element ref="ospass"/>
        <xs:element ref="repositories"/>
      </xs:sequence>
      <xs:attribute name="id" use="required" type="xs:NCName"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="ip" type="xs:NMTOKEN"/>
  <xs:element name="osuser" type="xs:NCName"/>
  <xs:element name="ospass" type="xs:NCName"/>
  <xs:element name="repositories">
    <xs:complexType>
      <xs:sequence>
        <xs:element maxOccurs="unbounded" ref="repository"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="repository">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="url"/>
        <xs:element ref="svnuser"/>
        <xs:element ref="svnpass"/>
      </xs:sequence>
      <xs:attribute name="name" use="required" type="xs:NCName"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="url" type="xs:anyURI"/>
  <xs:element name="svnuser" type="xs:NCName"/>
  <xs:element name="svnpass" type="xs:NCName"/>
</xs:schema>

El XSD generado es un XSD básico, sencillo y útil. Lo único que no termina de convencerme es la tipificación xs:NCName (Non Colonized Name) que le ha dado a las cadenas de texto. No es una tipificación incorrecta, pero limita el uso de qualified names (nombres con namespace) en el contenido del texto.

inst2xsd (http://xmlbeans.apache.org/index.html)

La herramienta inst2xsd viene incluida en el software XMLBEANS de Apache Foundation que se puede descargar directamente desde su página web. Esta herramienta es más completa que Trang, aunque sin ser difícil también es más compleja de utilizar.

Usage: inst2xsd [opts] [instance.xml]*
Options include:
    -design [rd|ss|vb] - XMLSchema design type
             rd  - Russian Doll Design - local elements and local types
             ss  - Salami Slice Design - global elements and local types
             vb  - Venetian Blind Design (default) - local elements and global complex types
    -simple-content-types [smart|string] - Simple content types detection (leaftext). Smart is the default
    -enumerations [never|NUMBER] - Use enumerations. Default value is 10.
    -outDir [dir] - Directory for output files. Default is '.'
    -outPrefix [file_name_prefix] - Prefix for output file names. Default is 'schema'
    -validate - Validates input instances agaist generated schemas.
    -verbose - print more informational messages
    -license - print license information
    -help - help imformation

Para generar el siguiente XML he utilizado la opción -enumerations never para evitar que los valores que se incluyen en el ejemplo se convierten en enumeraciones en el XSD final.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="servers" type="serversType"/>
  <xs:complexType name="repositoryType">
    <xs:sequence>
      <xs:element type="xs:anyURI" name="url"/>
      <xs:element type="xs:string" name="svnuser"/>
      <xs:element type="xs:string" name="svnpass"/>
    </xs:sequence>
    <xs:attribute type="xs:string" name="name" use="optional"/>
  </xs:complexType>
  <xs:complexType name="repositoriesType">
    <xs:sequence>
      <xs:element type="repositoryType" name="repository" maxOccurs="unbounded" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="serverType">
    <xs:sequence>
      <xs:element type="xs:string" name="ip"/>
      <xs:element type="xs:string" name="osuser"/>
      <xs:element type="xs:string" name="ospass"/>
      <xs:element type="repositoriesType" name="repositories"/>
    </xs:sequence>
    <xs:attribute type="xs:string" name="id" use="optional"/>
  </xs:complexType>
  <xs:complexType name="serversType">
    <xs:sequence>
      <xs:element type="serverType" name="server" maxOccurs="unbounded" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>
</xs:schema>

El XSD generado con esta herramienta es aún más simple que el generado con Trang. Los objetos que contienen texto los ha tipificado como xs:string que puede contener cualquier tipo de texto.

Conclusión

Existen más herramientas en el mercado para obtener ficheros XML Schema a partir de ficheros XML. Algunas son de pago, otras son más complejas, otras tienen interfaz gráfico, pero las dos herramientas descritas en esta entrada son suficientes para obtener XSD de calidad de forma fácil y gratuita.

Si bien me ha gustado más la generación de la herramienta inst2xsd por la generación menos restrictiva de las cadenas de texto, ambas herramientas han generado XSD aptos para utilizar con JAXB y poder generar las clases Java necesarias para tratar la información del XML.

Links

Xml Schema W3C
NCName

WSDL (VII) – wsdl:service y wsdl:port

Esta entrada es la séptima y última entrega dedicada al interesante mundo del WSDL. En esta entrada encontrarás en detalle los elementos wsdl:service y wsdl:port, que contiene la dirección del endpoint donde se va a publicar el servicio web.

Descripción

Wsdl:service forma parte del objeto wsdl:definitions.

Wsdl:port forma parte del elemento wsdl:service.

El elemento wsdl:port define el endpoint para un wsdl:binding concreto.

Gramática

La gramática del elemento wsdl:types es la siguiente (? –> es opcional, * –> pueden ser de 0 a N elementos):

<wsdl:service .... > *
 <wsdl:port name="nmtoken" binding="qname"> *
 <-- extensibility element (1) -->
 </wsdl:port>
</wsdl:service>

Atributos

El elemento wsdl:service cuenta con los siguientes atributos:

  • name: este atributo proporciona un nombre único para el servicio web. Debe coincidir con el atributo name del elemento wsdl:definitions.
El elemento wsdl:port cuenta con los siguientes atributos:
  • binding: esta atributo proporciona el nombre del wsdl:binding para el que se crea el endpoint.
  • name: este atributo proporciona un nombre único para este endpoint.

SubElementos

El elemento «extensibility element (1)» indica la información para construir la URI del endpoint. Un puerto sólo puede tener un endpoint. El elemento soap:address mediante el atributo location es el encargado de darle una URI donde se publica el servicio WEB.  

Ejemplo.

Este ejemplo muestra la definición de un binding para el portType AsistenteProducto. 

<wsdl:service nameAsistenteProductoSW«>
<wsdl:port bindingtns:AsistenteProductoSWSoapBinding« nameAsistenteProducto«>
</wsdl:port>
</wsdl:service>

Conclusión

El apartado wsdl:services es el qué marca la URI donde se publica el servicio web. Esta URI es la que se debe distribuir a los clientes que deben acceder a las funcionalidades proporcionadas por el servicio. 

Links

WSDL (VI) – wsdl:binding

Esta entrada es la sexta entrega dedicada al interesante mundo del WSDL. En esta entrada encontrarás en detalle el elemento wsdl:binding, que contiene los detalles sobre el formato del mensaje, así como del protocolo utilizado para transportar la información tanto de entrada como de salida.

Descripción

Wsdl:binding forma parte del objeto wsdl:definitions.

El elemento wsdl:binding define el formato del mensaje y los detalles del protocolo que se utiliza en los diferentes procesos de comunicación del servicio web. Es posible definir diferentes bindings asociados al mismo portType, por lo que un mismo servicio web puede implementar la comunicación a través de diferentes protocolos y dentro de cada operación definir diferentes configuraciones para la comunicación de entrada y de salida.

El tipo de binding elegido puede influir en la compatibilidad multiplataforma del servicio web 

Gramática

La gramática del elemento wsdl:types es la siguiente (? –> es opcional, * –> pueden ser de 0 a N elementos):

<wsdl:binding name="nmtoken" type="qname"> *
 <-- extensibility element (1) --> *
 <wsdl:operation name="nmtoken"> *
 <-- extensibility element (2) --> *
 <wsdl:input name="nmtoken"? > ?
 <-- extensibility element (3) --> 
 </wsdl:input>
 <wsdl:output name="nmtoken"? > ?
 <-- extensibility element (4) --> *
 </wsdl:output>
 <wsdl:fault name="nmtoken"> *
 <-- extensibility element (5) --> *
 </wsdl:fault>
 </wsdl:operation>
 </wsdl:binding>

Atributos

El elemento wsdl:binding cuenta con los siguientes atributos:

  • name: este atributo proporciona un nombre único que identifica el binding dentro del documento WSDL
  • type: este atributo enlaza el elemento wsdl:binding con el portType definido, de hecho, deben llevar el mismo nombre.

SubElementos

El elemento «extensibility element (1)» indica el tipo de binding que se elige para las operaciones especificadas. Cada elemento wsdl:binding solo puede hacer referencia a un único protocolo. Esto se hace indicando cualquiera de estos tres elementos:

  • <soap:binding style=»document | rpc» transport=»http://schemas.xmlsoap.org/soap/{http | smtp | ftp}»/>
  • <http:binding verb=»GET | POST»>
  • <mime:multipartRelated>
El primer binding es un binding basado en el protocolo SOAP. El segundo binding está basado en GET y POST de http y el último es el binding MIME que suele ir siempre ligado a mensajes de INPUT/OUTPUT de operaciones SOAP.  
 
El elemento wsdl:operation describe la operación sobre la que se va a aplicar información de binding. Esta información viaja en el elemento «extensibility element (2)» que detallará la información de binding propia de la operación.
 
El elemento wsdl:input describe el objeto de entrada al que se va a aplicar información de binding. Esta información viaja en el elemento «extensibility element (3)» que detallará la información de binding para el objeto de entrada de esta operación. 
 
El elemento wsdl:output describe el objeto de respuesta al que se va a aplicar información de binding. Esta información viaja en el elemento «extensibility element (4)» que detallará la información de binding para el objeto de respuesta de esta operación.
 
El elemento wsdl:fault describe en caso de fallo las características de binding. Esta información viaja en el elemento «extensibility element (5)» que detallará la información de binding para el objeto de error.
 

Ejemplo de SOAP Binding.

Este ejemplo muestra la definición de un binding para el portType AsistenteProducto. 

<wsdl:binding 
   name="AsistenteProductoSWSoapBinding" 
   type="tns:AsistenteProducto">
 <soap:binding 
    styledocument«    
 <wsdl:operation nameconsultaInteraccionesTratamientoCompleto«>     
   <soap:operation 
     soapAction/consultaInteraccionesTratamientoCompletoOP«          
     styledocument«/>
  <wsdl:input nameconsultaInteraccionesTratamientoCompleto«         
     <soap:body useliteral«/>
  </wsdl:input>
  <wsdl:output nameconsultaInteraccionesTratamientoCompletoResponse«>
    <soap:body useliteral«/>
  </wsdl:output>
 </wsdl:operation>
 <wsdl:operation nameconsultaDuplicidadesTratamientoNuevo«>
  <soap:operation 
      soapAction/consultaDuplicidadesTratamientoNuevoOP«      
      styledocument«/>
  <wsdl:input nameconsultaDuplicidadesTratamientoNuevo«>
    <soap:body useliteral«/>
  </wsdl:input>
  <wsdl:output nameconsultaDuplicidadesTratamientoNuevoResponse«>
    <soap:body useliteral«/>
  </wsdl:output>
 </wsdl:operation>
 <wsdl:operation nameconsultaDuplicidadesTratamientoCompleto«>
  <soap:operation 
      soapAction/consultaDuplicidadesTratamientoCompletoOP«       
      styledocument«/>
  <wsdl:input nameconsultaDuplicidadesTratamientoCompleto«>
    <soap:body useliteral«/>
  </wsdl:input>
  <wsdl:output nameconsultaDuplicidadesTratamientoCompletoResponse«>
    <soap:body useliteral«/>
  </wsdl:output>
 </wsdl:operation>
 <wsdl:operation nameconsultaInteraccionesTratamientoNuevo«>
  <soap:operation 
     soapAction/consultaInteraccionesTratamientoNuevoOP«    
     styledocument«/>
  <wsdl:input nameconsultaInteraccionesTratamientoNuevo«>
    <soap:body useliteral«/>
  </wsdl:input>
  <wsdl:output nameconsultaInteraccionesTratamientoNuevoResponse«>
    <soap:body useliteral«/>
  </wsdl:output>
 </wsdl:operation>
</wsdl:binding>

En el ejemplo se puede ver que el binding es de tipo SOAP a través de HTTP. El estilo de SOAP en este caso es document.  Si no se pone nada, el estilo seguirá siendo «document«.  

<wsdl:binding 
   name="AsistenteProductoSWSoapBinding" 
   type="tns:AsistenteProducto">
 <soap:binding 
    style="document"    
    transport="http://schemas.xmlsoap.org/soap/http"/>

Podemos ver que cada operación puede definir un SOAP style propio, teniendo como posibles valores también RPC y DOCUMENT. En el ejemplo no se indica, por defecto el estilo es document. El campo soapAction especifica el valor de cabecera SOAPAction. En el caso de protocolo SOAP sobre HTTP, el valor SOAPAction de la cabecera es obligatorio, por lo que siempre habrá que rellenarlo. 

<soap:operation 
  soapAction="/consultaDuplicidadesTratamientoNuevoOP"      
    style="document"/>

Cada elemento que conforma la operación, wsdl:input, wsdl:output o wsdl:fault definen el elemento soap:body. Este elemento especifica como se incluyen los elementos wsdl:parts en el elemento SOAP Body.  El atributo use marca la codificación que se realiza en la información, y puede ser literal o encoded. En el ejemplo, el objeto de entrada de consultaInteraccionesTratamientoNuevo la codificación del body se realiza de forma literal

<wsdl:input name="consultaInteraccionesTratamientoNuevo">
    <soap:body useliteral«/>
</wsdl:input>

 

DOCUMENT versus RPC

A la hora de especificar dentro de las operaciones SOAP como queremos que se vea el mensaje transportado la definición del atributo style de la etiqueta soap:binding o soap:operation (si queremos aplicar un estilo diferente por cada operación) es la clave. 

El atributo style puede tomar dos posibles valores: document y rpc (remote procedure call). 

Un mensaje SOAP de estilo RPC se construye con la idea de invocar al servicio web como si fuera un método de una aplicación. Por tanto, el cuerpo del mensaje SOAP contiene un elemento XML por cada parámetro que necesita el método y estos elementos de parámetro se incluyen en otro elemento superior que representa el nombre del método al que se llama. El WSDL para una operación codificada en RPC es menos compleja que sus hermanas codificadas en estilo DOCUMENT. 

Un ejemplo de mensaje SOAP RPC es:

<soap:envelope>
  <soap:body>
    <multiply>    <!-- web method name -->
      <a>2.0</a>  <!-- first parameter -->
      <b>7</b>    <!-- second parameter -->
    </multiply>
  </soap:body>
</soap:envelope>

Un mensaje SOAP de estilo DOCUMENT, sin embargo, no contiene restricciones en la construcción del cuerpo del mensaje. Permite la inclusión libre de datos en formato XML representados por un Schema XML. De esta forma, el cliente y el proveedor son los encargados de hacer el trabajo de marshall y unmarshall. Esto contrasta con RPC donde este trabajo de marshal y unmarshall debe ser realizado por la librería SOAP que se esté utilizando. 

Un ejemplo de mensaje SOAP DOCUMENT es:

<soap:envelope>
  <soap:body>
    <!-- arbitrary XML -->
    <movies xmlns="http://www.myfavoritemovies.com">
      <movie>
        <title>2001: A Space Odyssey</title>
        <released>1968</released>
      </movie>
      <movie>
        <title>Donnie Darko</title>
        <released>2001</released>
      </movie>
    </movies>
  </soap:body>
</soap:envelope>

 

La gran ventaja de RPC sobre DOCUMENT es que es fácilmente interpretable por humanos. Sin embargo, esta ventaja no es tal, ya que no tiene gran utilidad que los humanos podamos leer de forma fácil los WSDL.

Por otro lado, esta ventaja, se convierte en desventaja debido al acoplamiento tan fuerte que hay con el código de la aplicaciónlo. Esto quiere decir, por ejemplo,  que si se quiere realizar un cambio en el orden de los parámetros implica irremediablemente un cambio en la definición del servicio web. 

Sin embargo, el estilo DOCUMENT tiene un acoplamiento muy débil con el código de la aplicación. La gran ventaja es que cambios realizados en el orden de los parámetros o incluso en el tipo de los mismos no influyen en la definición del servicio web. La desventaja  es que el SOAP generado es más difícil de interpretar visualmente por una persona (lo que tampoco tiene porque ser una gran desventaja).

Además, el que no haya reglas específicas para la generación de SOAP en el estilo DOCUMENT es una ventaja/desventaja. Es ventaja porque nos permite libertad total a la hora de codificar la información y es una desventaja porque el trabajo de MARSHALL y UNMARSHALL recae en el cliente y en el proveedor.

Encoded versus Literal

La otra gran opción a la hora de determinar el aspecto final del código SOAP generado es el atributo use del elemento soap:body, que puede tomar valores encoded o literal.

El uso Literal implica que el cuerpo SOAP sigue un esquema XML para definir su contenido. Este esquema XML se incluye en el apartado wsdl:types del WSDL. Por tanto, siempre que el cliente tenga acceso al WSDL sabrá como debe hacer el marshall/unmarshall del documento.

El uso Encoded, sin embargo, implica que el cuerpo SOAP no sigue ningún esquema XML, aunque tenga que seguir un formato específico que incluya la información para que el cliente sepa como hacer el marshall y el unmarshall de la información. El modo encoded no es recomendable y no está aceptado por el estándar WS-I, debido a las incompatibilidades que las diferentes implementaciones SOAP hagan en los diferentes frameworks de servicios web y los diferentes lenguajes de programación.

Conclusión

El apartado wsdl:binding es el qué más problemas de incompatibilidad puede dar en el uso multiplataforma de un servicio web. En él se define el protocolo utilizado en la comunicación, así como la codificación de la información que viaja por cada operación. 

Es recomendable que la codificación se realice siempre en estilo DOCUMENT y uso LITERAL. De esta forma nos aseguramos libertad en el envío de la información y garantizamos que dicha información cumple un esquema que facilita el tratamiento de la misma.

Links

WSDL (V) – wsdl:portType

Esta entrada es la quinta dedicada al interesante mundo del WSDL. En esta entrada encontrarás en detalle el elemento wsdl:portType, que contiene la definición de las operaciones que se incluyen en el servicio web.

Descripción

Wsdl:portType forma parte del objeto wsdl:definitions.

El elemento wsdl:portType define un grupo de operaciones que forman parte del servicio web. Este elemento también es conocido como interface, de hecho en la nueva especificación WSDL 1.2 (que en el momento de escribir este artículo se encuentra en estado «draft«) se sustituye el termino «portType» por el de «interface«. 

Gramática

La gramática del elemento wsdl:types es la siguiente (? –> es opcional, * –> pueden ser de 0 a N elementos):

 <wsdl:portType name="nmtoken">
<wsdl:operation name="nmtoken" .... /> *
</wsdl:portType>

Atributos

El principal atributo del elemento wsdl:portType es name. Este nombre servirá para identificar este portType en el apartado wsdl:binding, de forma que cada portType pueda tener sus propias características de envío. 

SubElementos

El elemento wsdl:operation contiene la información de las diferentes operaciones que se incluyen en el portType. Este elemento wsdl:operation puede estar formado por los siguientes elementos:

  • wsdl:input para definir el mensaje de entrada 
  • wsdl:output para definir el mensaje de salida
  • wsdl:fault para definir el mensaje en caso de error. 

 El orden en el que se presentan estos elementos define el patrón de intercambio de mensajes utilizado. 

  • Patrón One-way. El endpoint recibe un mensaje. Se define solamente un elemento de entrada.
  • Patrón Request-response. El endpoint recibe un mensaje y envía la correspondiente respuesta. Se define un elemento de entrada seguido de uno de salida. 
  • Patrón Solicit-Response. El endpoint envía un mensaje y recibe la respuesta correspondiente. Se define un elemento de salida y seguido uno de entrada. 
  • Patrón Notification. El endpoint envia un mensaje. Se define un elemento de salida. 

 

Ejemplo

Este ejemplo muestra el portType AsistenteProducto

<wsdl:portType name="AsistenteProducto">
<wsdl:operation nameconsultaInteraccionesTratamientoCompleto«>
<wsdl:input messagetns:consultaInteraccionesTratamientoCompleto« nameconsultaInteraccionesTratamientoCompleto«></wsdl:input>
<wsdl:output messagetns:consultaInteraccionesTratamientoCompletoResponse« nameconsultaInteraccionesTratamientoCompletoResponse«></wsdl:output>
</wsdl:operation>

<wsdl:operation nameconsultaDuplicidadesTratamientoNuevo«>
<wsdl:input messagetns:consultaDuplicidadesTratamientoNuevo« nameconsultaDuplicidadesTratamientoNuevo«></wsdl:input>
<wsdl:output messagetns:consultaDuplicidadesTratamientoNuevoResponse« nameconsultaDuplicidadesTratamientoNuevoResponse«></wsdl:output>
</wsdl:operation>

<wsdl:operation nameconsultaInteraccionesTratamientoNuevo«>
<wsdl:input messagetns:consultaInteraccionesTratamientoNuevo« nameconsultaInteraccionesTratamientoNuevo«></wsdl:input>
<wsdl:output messagetns:consultaInteraccionesTratamientoNuevoResponse« nameconsultaInteraccionesTratamientoNuevoResponse«></wsdl:output>
</wsdl:operation>

<wsdl:operation nameconsultaDuplicidadesTratamientoCompleto«>
<wsdl:input messagetns:consultaDuplicidadesTratamientoCompleto« nameconsultaDuplicidadesTratamientoCompleto«></wsdl:input>
<wsdl:output messagetns:consultaDuplicidadesTratamientoCompletoResponse« nameconsultaDuplicidadesTratamientoCompletoResponse«></wsdl:output>
</wsdl:operation>
</wsdl:portType>

Como podemos observar  el portType está formado por 4 operaciones, cada una con su entrada y salida propias:

  • consultaInteraccionesTratamientoCompleto
  • consultaDuplicidadesTratamientoNuevo
  • consultaInteraccionesTratamientoNuevo
  • consultaDuplicidadesTratamientoCompleto 
Todas las operaciones definidas siguen el patrón Request – Response, de forma que para que cualquier operación de este servicio web devuelva información debe recibir primero una petición informada.
 
Si generamos un cliente con este portType obtendremos una estructura similar a la que se muestra en la siguiente imagen:
 
Operaciones incluidas en un portType y en un binding

Conclusión

El apartado wsdl:portType indica las operaciones que se van a incluir de forma pública en el servicio web.

WSDL (IV) – wsdl:messages

Esta entrada es la cuarta entrega dedicada al interesante mundo de los WSDL. En esta entrada encontrarás en detalle el elemento wsdl:messages, que define los mensaje abstractos que sirven de entrada y salida de las operaciones.

Descripción

Wsdl:messages forma parte del objeto wsdl:definitions.

El elemento wsdl:messages define los mensaje abstractos que sirven de entrada y salida de las operaciones.

Estos mensajes abstractos agrupan los diferentes tipos de datos definidos en wsdl:types y conforman finalmente la entrada o salida del servicio web.

Para agrupar los tipos de datos el elemento wsdl:messages utiliza el elemento wsdl:part, de forma que si un mensaje incluye varios tipos de datos, cada uno de ellos irá incluido en un elemento wsdl:part.

Gramática

La gramática del elemento wsdl:types es la siguiente (? –> es opcional, * –> pueden ser de 0 a N elementos):

<wsdl:message name="nmtoken"> *
  <wsdl:documentation .... />?
  <wsdl:part name="nmtoken" element="qname"? type="qname"?/> *
</wsdl:message>

Atributos

El principal atributo del elemento wsdl:message es name. Este nombre servirá para identificar el mensaje cuando se definan las operaciones en el elemento wsdl:portType.

SubElementos

El elemento wsdl:documentation es opcional y muestra la información general de los mensajes definidos en este apartado. 

El elemento wsdl:part define el o los tipos de datos que participan en el mensaje.

Ejemplo

Este ejemplo muestra la definición del mensaje consultaDuplicidadesTratamientoNuevo, que será el objeto input de la operación ConsultaDuplicidadesTratamientoNuevo del servicio web AsistenteProductoWS. 

<wsdl:definitions xmlns:asp="http://VDM/esquemas/asistenteproducto" [...]
<wsdl:message name="consultaDuplicidadesTratamientoNuevo">
   <wsdl:part 
      elementasp:ConsultaDuplicidadesTratamientoNuevoPet«   
      nameparameters«></wsdl:part>
</wsdl:message>

Este mensaje está formado por un único tipo de dato que es ConsultaDuplicidadesTratamientoNuevoPet. 

Ejemplo de generación de objeto de entrada a partir del wsdl:messages de ejemplo anteriores.

Si generamos el cliente para cualquiera de las operaciones del servicio web obtendremos un código similar al siguiente: 

<soapenv:Envelope 
     xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
     xmlns:asis="http://VDM/esquemas/asistenteproducto">
     <soapenv:Header/>
<soapenv:Body>
<asis:ConsultaDuplicidadesTratamientoNuevoPet>
<Cabecera>
<FechaHoraPet>?</FechaHoraPet>
<Idioma>?</Idioma>
<IdTransaccion>?</IdTransaccion>
</Cabecera>
<TratamientoNuevo>
<IdPrescripcion>?</IdPrescripcion>
<IdUnicoProducto>?</IdUnicoProducto>
</TratamientoNuevo>
<!--1 or more repetitions:-->
<TratamientosComparacion>
<IdPrescripcion>?</IdPrescripcion>
<IdUnicoProducto>?</IdUnicoProducto>
</TratamientosComparacion>
</asis:ConsultaDuplicidadesTratamientoNuevoPet>
</soapenv:Body>
</soapenv:Envelope>

Conclusión

El apartado wsdl:messages es una abstracción más que agrupa definitivamente los inputs y los outputs de las operaciones que se definen en wsdl:portType.

Si la definición de los tipos de datos es buena, los mensajes deberían quedar correctamente estructurados y hacer entendible de un sólo vistazo cual es la entrada y la salida de una operación en un servicio web. 

WSDL (III) – wsdl:types

Esta entrada es la tercera que estoy dedicando al interesante mundo del WSDL. En esta entrada encontrarás en detalle el elemento wsdl:types, que contiene la definición de los tipos de datos que se utilizan en las operaciones del servicio web. Es muy importante definir estos tipos de datos para garantizar que la comunicación entre el cliente y el proveedor del servicio se entienden sin errores.

Descripción

Wsdl:types forma parte del objeto wsdl:definitions.

El elemento wsdl:types define directamente los tipos de datos que se utilizan en las operaciones del servicio web. Esta definición de tipos se realiza mediante Esquemas XML (XSD) que son los encargados de validar el correcto formato de los mensajes en la comunicación entre cliente y proveedor.

Gramática

La gramática del elemento wsdl:types es la siguiente (? –> es opcional, * –> pueden ser de 0 a N elementos):

<wsdl:types> ?
   <wsdl:documentation .... />?
     <xsd:schema .... />*
     <-- extensibility element --> *
</wsdl:types>

SubElementos

El elemento wsdl:documentation es opcional y muestra la información general de los tipos de datos que se definen en este apartado. 

El elemento xsd:schema define los tipos de datos haciendo uso de esquemas XML. Esta definición puede hacerse de dos maneras: 

  • Directamente en el WSDL utilizando el lenguaje XSD.
  • Importando un XSD ya existente en el WSDL.

Ejemplo de WSDL con tipos de datos incluidos implícitamente.

Este ejemplo muestra la definición del tipo de dato ConsultaDuplicidadesTratamientoNuevoPet que es la entrada (input) de la operación ConsultaDuplicidadesTratamientoNuevo que proporciona el servicio web AsistenteProductoWS. 

<xsd:schema

   xmlns:Q1=»http://VDM/esquemas/comun»

   xmlns:this=»http://VDM/esquemas/asistenteproducto»

   xmlns:xsd=»http://www.w3.org/2001/XMLSchema»

   targetNamespace=»http://VDM/esquemas/asistenteproducto»>

     

  <xsd:complexType nametipoCabecera«>

    <xsd:annotation>
    <xsd:documentation>
   Todas las peticiones que reciba el sistema universal de prescripción tendrán una cabecera    fija. Los datos de esta cabecera están en este tipo.
      </xsd:documentation>
      </xsd:annotation>
      <xsd:sequence>
      <xsd:element nameFechaHoraPet« typexsd:dateTime«>
      <xsd:annotation>
      <xsd:documentation>Fecha y hora de la petición</xsd:documentation>
      </xsd:annotation>
      </xsd:element>
      <xsd:element nameIdioma« typethis:tipoIdioma«>
      <xsd:annotation>
      <xsd:documentation>
     Idioma de la petición. Pudiendo ser los valores indicados en el tipo tipoIdioma: Euskera y Castellano.
      </xsd:documentation>
      </xsd:annotation>
      </xsd:element>
      <xsd:element nameIdTransaccion« typexsd:string«>
      <xsd:annotation>
       <xsd:documentation>
      El id de transacción es único para cada petición y generado por la aplicación cliente de la plataforma SUPRE.
       </xsd:documentation>
      </xsd:annotation>
      </xsd:element>
      </xsd:sequence>
     </xsd:complexType>

     <xsd:complexType nametipoElementoConsultaDuplicidades«>
     <xsd:annotation>
      <xsd:documentation>Información para la consulta de duplicidades</xsd:documentation>
     </xsd:annotation>
     <xsd:sequence>
     <xsd:element nameIdPrescripcion« typexsd:string«>
      <xsd:annotation>
       <xsd:documentation>Identificador de prescripción</xsd:documentation>
      </xsd:annotation>
     </xsd:element>
     <xsd:element nameIdUnicoProducto« typexsd:long«>
      <xsd:annotation>
       <xsd:documentation>Identificador único de producto de la prescripción</xsd:documentation>
      </xsd:annotation>
     </xsd:element>
     </xsd:sequence>
     </xsd:complexType>

     <xsd:complexType name=»tipoConsultaDuplicidadesTratamientoNuevoPet»>

       <xsd:annotation>

          <xsd:documentation>Información de la petición</xsd:documentation>

       </xsd:annotation>

       <xsd:sequence>

          <xsd:element name=»Cabecera» type=»this:tipoCabecera»>

             <xsd:annotation>

               <xsd:documentation>Información de la cabecera</xsd:documentation>

             </xsd:annotation>

          </xsd:element>

          <xsd:element name=»TratamientoNuevo» type=»this:tipoElementoConsultaDuplicidades»>

            <xsd:annotation>

              <xsd:documentation>

              Datos del tratamiento nuevo para comprobar su duplicidad

              </xsd:documentation>

            </xsd:annotation>

          </xsd:element>

          <xsd:element 

              maxOccurs=»unbounded» 

              name=»TratamientosComparacion» 

              type=»this:tipoElementoConsultaDuplicidades»>

             <xsd:annotation>

               <xsd:documentation>

                 Lista de datos de tratamiento que ya tenía el paciente para comprobar su duplicidad

               </xsd:documentation>

             </xsd:annotation>

          </xsd:element>

       </xsd:sequence>

     </xsd:complexType>


     <xsd:element 

         name=»ConsultaDuplicidadesTratamientoNuevoPet»

         type=»this:tipoConsultaDuplicidadesTratamientoNuevoPet»>

        <xsd:annotation>

           <xsd:documentation>Consulta de duplicidades que permite comprobar si un Principio Activo ATC no está duplicado en otros con el resto de prescripciones ya creadas. La respuesta esperada es una lista de pares del Tratamiento Nuevo con alguno de los tratamientos que ya tenía el paciente

           </xsd:documentation>

        </xsd:annotation>

     </xsd:element>

</xsd:schema>

 

El elemento base que define el tipo de dato ConsultaDuplicidadesTratamientoNuevoPet está definido en verde.

<xsd:element 
     name="ConsultaDuplicidadesTratamientoNuevoPet"
     type="this:tipoConsultaDuplicidadesTratamientoNuevoPet"
</xsd:element>

 

Entre sus atributos destacan el nombre del tipo de dato y el tipo, que en este caso es un tipo de dato complejo definido en el elemento tipoConsultaDuplicidadesTratamientoNuevoPet de wsdl:types. Este elemento, tal y como indica el prefijo this, se tiene que encontrar en este mismo fichero. Si nos fijamos en los namespaces incluidos en el elemento xsd:schema veremos que hace referencia a sí mismo http://VDM/esquemas/asistenteproduto

xsd:schema
   targetNamespace="http://VDM/esquemas/asistenteproducto"
   xmlns:Q1="http://VDM/esquemas/comun"
   xmlns:this="http://VDM/esquemas/asistenteproducto"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema"   

 

El objeto tipoConsultaDuplicidadesTratamientoNuevoPet está definido por una secuencia de tres elementos, una cabecera, un tratamiento nuevo y una lista de tratamientos de comparación. 

<xsd:complexType name="tipoConsultaDuplicidadesTratamientoNuevoPet">
  <xsd:sequence>
    <xsd:element name="Cabecera" type="this:tipoCabecera">
    <xsd:element name="TratamientoNuevo" type="this:tipoElementoConsultaDuplicidades">
    <xsd:element 
       maxOccurs="unbounded" 
       name="TratamientosComparacion
       type="this:tipoElementoConsultaDuplicidades">
  </xsd:sequence>
</xsd:complexType>


El elemento Cabecera es un elemento complejo definido en un objeto this.tipoCabecera que está definido en el propio WSDL. El elemento TratamientoNuevo es un elemento complejo definido en el objeto this.tipoElementoConsultaDuplicidades también definido en el propio WSDL. El elemento TratamientosComparacion es un elemento complejo definido por el mismo objeto que TratamientoNuevo, sólo que esta vez se repite ilimitadamente (maxOccurs=»unbounded»). 

Si un elemento no tiene definido el atributo maxOccurs por defecto tomará el valor «1«. El valor «unbounded» indica que el elemento puede repetirse de forma ilimitada.

La definición de los elementos tipoCabecera y tipoElementoConsultaDuplicidades se encuentran también en el elemento wsdl:types. En el ejemplo se muestran en azul. Estos objetos complejos están definidos por elementos primitivos. Por ejemplo, el tipo complejo tipoElementoConsultaDuplicidades está formado por dos tipos primitivos, IdPrescripcion que es un xsd:string y IdUnicoProducto que es un xsd:long.  

     <xsd:complexType name="tipoElementoConsultaDuplicidades">
     <xsd:sequence>
     <xsd:element nameIdPrescripcion« typexsd:string«>
   <xsd:element nameIdUnicoProducto« typexsd:long«>
  </xsd:sequence>
     </xsd:complexType>

Los tipos primitivos válidos se pueden encontrar en el apartado datatypes de la especificación Schema XML. 

Ejemplo de WSDL con tipos de datos importados.

Importar el tipo de datos aporta sencillez al diseño del WSDL facilitando la identificación a primera vista de los tipos de datos. Si se quiere profundizar en los mismos se podrá acceder a través de la URI de schemaLocation al detalle del tipo de dato que está definido en su correspondiente XSD.

En el siguiente ejemplo se define el tipo de dato ConsultaDuplicidadesTratamientoNuevoPet pero utilizando ésta vez un fichero xsd. 

<wsdl:types>
  <xsd:schema 
     xmlns:asp="http://VDM/esquemas/asistenteproducto"
     xmlns:ns1="http://cxf.apache.org/bindings/xformat"       
     xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
     xmlns:tns="http://VDM/wsdls/AsistenteProductoWSDL" 
     xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
     xmlns:xs="http://www.w3.org/2001/XMLSchema"     
     xmlns:xsd="http://www.w3.org/2001/XMLSchema"
     elementFormDefault="unqualified" 
     targetNamespace="http://VDM/wsdls/AsistenteProductoWSDL" 
     version="1.0">
   
   <xsd:import 
                      xsd=xsd/ConsultaDuplicidadesTratamientoNuevoPet.xsd«/>
 </xs:schema>
</wsdl:types>

Claramente se ve que el diseño del WSDL es mucho más sencillo que en el ejemplo anterior. Sin embargo, si queremos ver el detalle de la información se hace necesario navegar a la URI del atributo schemaLocation y acceder al XSD.

Este XSD contendrá un código similar al del ejemplo anterior, pudiendo tener a su vez importaciones a otros XSDs que especifiquen los objetos complejos tipoCabecera y tipoElementoConsultaDuplicidades que podrían estar definidos en sus propios XSDs.

Ejemplo de generación de objeto de entrada a partir de los wsdl:types de ejemplo anteriores.

Si generamos el cliente para cualquiera de las operaciones del servicio web obtendremos un código similar al siguiente: 

<soapenv:Envelope 
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:asis="http://VDM/esquemas/asistenteproducto">
   <soapenv:Header/>
   <soapenv:Body>
      <asis:ConsultaDuplicidadesTratamientoNuevoPet>
         <Cabecera>
             <FechaHoraPet>?</FechaHoraPet>
             <Idioma>?</Idioma>
             <IdTransaccion>?</IdTransaccion>
         </Cabecera>
         <TratamientoNuevo>
             <IdPrescripcion>?</IdPrescripcion>
             <IdUnicoProducto>?</IdUnicoProducto>
         </TratamientoNuevo>
         <!--1 or more repetitions:-->
         <TratamientosComparacion>
             <IdPrescripcion>?</IdPrescripcion>
             <IdUnicoProducto>?</IdUnicoProducto>
         </TratamientosComparacion>
      </asis:ConsultaDuplicidadesTratamientoNuevoPet>
   </soapenv:Body>
</soapenv:Envelope>

Conclusión

El apartado wsdl:types es uno de los más importantes en la descripción del Web Service ya que permite generar una correcta comunicación entre proveedor y cliente. 

Esta claro que hay que encontrar un equilibrio en la definición de los tipos de datos a través de XSDs. Si hay pocos XSDs, nos encontraremos con un fichero inmenso difícil de manejar, y si por el contrario, definimos demasiados XSDs, tendremos que navegar por todos ellos para enterarnos de los datos que participan en el servicio web, y si no disponemos de un buen mapa de objetos podemos perder la visión de lo datos. 

Links

WSDL (II) – wsdl:definitions

Esta entrada forma parte de la incursión en el interesante mundo del WSDL, comenzada en la entrada WSDL(I) – Introducción. El WSDL es conocida como la especificación estándar que permite detallar el contenido de un servicio web mediante XML. En esta entrada detallo el elemento wsdl:definitions, que es el elemento principal en la definición de un servicio web y es el primero que se aborda.

Descripción

Wsdl:definitions es el elemento raíz de todo WSDL.

En él se incluye toda la información necesaria para describir el servicio web; las operaciones que publica el servicio web, los tipos de datos que se utilizan en las operaciones, los tipos de binding dependiendo del protocolo que se utiliza en la llamada al servicio web y la url en la que es publicado y a la que se debe llamar para invocarlo. 

Gramática

La gramática completa del elemento definitions es la siguiente (? –> campo opcional; * –> 0 a N campos): 

<wsdl:definitions name="nmtoken"? targetNamespace="uri"?>

    <import namespace="uri" location="uri"/>*

    <wsdl:documentation .... /> ?

    <wsdl:types> ?
        <wsdl:documentation .... />?
        <xsd:schema .... />*
        <-- extensibility element --> *
    </wsdl:types>

    <wsdl:message name="nmtoken"> *
        <wsdl:documentation .... />?
        <part name="nmtoken" element="qname"? type="qname"?/> *
    </wsdl:message>

    <wsdl:portType name="nmtoken">*
        <wsdl:documentation .... />?
        <wsdl:operation name="nmtoken">*
           <wsdl:documentation .... /> ?
           <wsdl:input name="nmtoken"? message="qname">?
               <wsdl:documentation .... /> ?
           </wsdl:input>
           <wsdl:output name="nmtoken"? message="qname">?
               <wsdl:documentation .... /> ?
           </wsdl:output>
           <wsdl:fault name="nmtoken" message="qname"> *
               <wsdl:documentation .... /> ?
           </wsdl:fault>
        </wsdl:operation>
    </wsdl:portType>

    <wsdl:binding name="nmtoken" type="qname">*
        <wsdl:documentation .... />?
        <-- extensibility element --> *
        <wsdl:operation name="nmtoken">*
           <wsdl:documentation .... /> ?
           <-- extensibility element --> *
           <wsdl:input> ?
               <wsdl:documentation .... /> ?
               <-- extensibility element -->
           </wsdl:input>
           <wsdl:output> ?
               <wsdl:documentation .... /> ?
               <-- extensibility element --> *
           </wsdl:output>
           <wsdl:fault name="nmtoken"> *
               <wsdl:documentation .... /> ?
               <-- extensibility element --> *
           </wsdl:fault>
        </wsdl:operation>
    </wsdl:binding>

    <wsdl:service name="nmtoken"> *
        <wsdl:documentation .... />?
        <wsdl:port name="nmtoken" binding="qname"> *
           <wsdl:documentation .... /> ?
           <-- extensibility element -->
        </wsdl:port>
        <-- extensibility element -->
    </wsdl:service>

    <-- extensibility element --> *

</wsdl:definitions>

 

Atributos

El elemento wsdl:definitions contiene los siguientes atributos:

  • name. Este atributo es el nombre del servicio web. Conviene que este nombre sea el mismo que el nombre utilizado en el apartado wsdl:service.
  • targetNamespace. Este atributo permite al WSDL referirse a si mismo y establecer los namespaces que se usan en la descripción. La URI que se da para definir el namespace propio no tiene porque existir, basta con que sea un valor único y diferente a los otros namespaces definidos. Además, la URI no puede ser una ruta relativa. 

Subelementos.

Los subelementos de wsdl:definitions contienen la descripción completa del servicio web. Dada su importancia y para organizar mejor este conocimiento, estos subelementos los iré comentando en sus propias entradas.
 

Ejemplo básico.

A continuación se muestra un ejemplo básico de un elemento wsdl:definitions que se utiliza en el servicio web AsistenteProductoSW.
<wsdl:definitions 
name="AsistenteProductoSW"
targetNamespace="
http://VDM/wsdls/AsistenteProductoWSDL"
xmlns:asp="http://VDM/esquemas/asistenteproducto"
xmlns:ns1="http://cxf.apache.org/bindings/xformat"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://VDM/wsdls/AsistenteProductoWSDL"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

Del ejemplo se pueden deducir varias cosas:

WSDL (I) – Introducción.

WSDL es el acrónimo de Web Services Description Language (en castellano Lenguaje para la Definición de Servicios Web) y es una especificación estándar que, basada en XML, sirve para definir todos los elementos que conforman un servicio web. Estos elementos descritos desde el WSDL pueden ser:

  • Información del interface describiendo todas las funciones disponibles.
  • Información de los tipos de datos que se utilizan en los mensajes de petición y de respuesta de las funciones.
  • Información del tipo de binding utilizado sobre el protocolo que usado en la comunicación con el servicio.
  • Información de la ubicación del servicio y la url desde la que se puede acceder a esta información.

Se podría resumir que WSDL proporciona el contrato de un servicio entre la entidad que lo solicita y la que lo proporciona, de forma que usando el WSDL, un cliente puede localizar un servicio web e invocar cualquiera de sus funciones de forma correcta.

El WSDL se divide principalmente en los siguiente grupos de elementos:

wsdl:definitions
  import
  wsdl:types
    xsd:schema
  wsdl:message
    part
  wsdl:portType
    wsdl:operation
      wsdl:input
      wsdl:output
      wsdl:fault
  wsdl:binding
    wsdl:operation
      wsdl:input
      wsdl:output
      wsdl:fault
   wsdl:service 
     wsdl:port

wsdl:definitions.

El elemento definitions es el elemento raíz de todo WSDL y en él se incluye toda la información necesaria para describir el servicio web; las operaciones que publica el servicio web, los tipos de datos que se utilizan en las operaciones, los tipos de binding dependiendo del protocolo que se utiliza en la llamada al servicio web y la url en la que es publicado y a la que se debe llamar para invocarlo. 

wsdl:types.

El elemento wsdl:types define directamente los tipos de datos que se utilizan en las operaciones del servicio web. Esta definición de tipos se realiza mediante Esquemas XML (XSD) que validan el formato de los mensajes en la comunicación. 

wsdl:messages

El elemento wsdl:messages define los mensaje abstractos que sirven de entrada y salida de las operaciones. Estos mensajes están formados por una o más parts. Estas parts están asociada con un elemento o un tipo de dato de los definidos en wsdl:types.

wsdl:portType (wsdl:interfaces)

El elemento wsdl:portType define un grupo de operaciones a incluir en el servicio web. Este elemento también es conocido como interface, de hecho en la nueva especificación WSDL 1.2 (que en el momento de escribir este artículo se encuentra en estado “draft”) se sustituye el termino “portType” por el de “interface”.  

Cada portType debe tener un nombre único para referirse a él desde cualquier parte en el WSDL. El portType puede contener una o más operaciones. Cada operación contiene una combinación de elementos de entrada y salida. También puede definirse un elemento fault para manejar los errores. El orden de estos elementos es importante porque define el patrón de intercambio de mensajes utilizado. 

  • Patrón One-way. El endpoint recibe un mensaje. Se define solamente un elemento de entrada.
  • Patrón Request-response. El endpoint recibe un mensaje y envía la correspondiente respuesta. Se define un elemento de entrada seguido de uno de salida. 
  • Patrón Solicit-Response. El endpoint envía un mensaje y recibe la respuesta correspondiente. Se define un elemento de salida y seguido uno de entrada. 
  • Patrón Notification. El endpoint envia un mensaje. Se define un elemento de salida. 

wsdl:binding

El elemento wsdl:binding define el formato del mensaje y los detalles del protocolo que se utiliza en la comunicación con el servicio web, de hecho, puede haber diferentes bindings asociados al mismo portType, por lo que un mismo servicio web puede implementar la comunicación a través de diferentes protocolos. 

En los elementos wsdl:binding sólo se puede especificar un único protocolo; SOAP, GET/POST o MIME

En los elementos wsdl:binding no se puede aportar ninguna información sobre la dirección de publicación del servicio web ya que esta información se proporciona en el elemento wsdl:port del elemento wsdl:service.

wsdl:service y wsdl:port

El elemento wsdl:service contiene los wsdl:port que se publican en el servicio web.  

El elemento wsdl:port define un endpoint individual especificando para cada binding definido en wsdl:binding una dirección única de acceso. 

Por tanto, el elemento wsdl:service proporciona la información necesaria para poder acceder a las diferentes funcionalidades proporcionadas por el servicio web.