2. Tipos de dados

Algumas mensagens SOAP definem tipos de dados, quer para argumentos de funcionalidades remotas que estão a ser invocadas (Pedido) quer para resultados (Resposta). Esses tipos de dados são especificados recorrendo aos XML Schemas.

Os tipos de dados podem ser divididos em duas categorias: simples e estruturados.

2.1. Tipos simples

Numa filosofia de fomentar a interoperabilidade entre sistemas, o SOAP foi buscar aos XML Schemas, o atributo xsi:type para indicar qual o tipo de cada elemento, onde xsi é o prefixo de um Namespace associado ao URI identificador do XML Schema-Instance. No exemplo apresentado anteriormente, analisamos uma resposta que corresponde ao seguinte pedido:

Exemplo 1.4. O atributo type numa mensagem SOAP

POST /nusoap-0.9.5/Soma2nums/serv-aritmetica3.php HTTP/1.0
Host: localhost:8888
User-Agent: NuSOAP/0.9.5 (1.123)
Content-Type: text/xml; charset=ISO-8859-1
SOAPAction: "uri:ws.di.uminho.pt/Aritmetica/mul"
Content-Length: 538

<?xml version="1.0" encoding="ISO-8859-1"?>
<SOAP-ENV:Envelope 
    SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
  <SOAP-ENV:Body>
    <ns3085:soma xmlns:ns3085="uri:ws.di.uminho.pt/Aritmetica">
      <n1 xsi:type="xsd:string">4.2</n1>
      <n2 xsi:type="xsd:string">2.1</n2>
    </ns3085:soma>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Repare na declaração do prefixo xsi e na utilização do atributo xsi:type para qualificar o tipo de conteúdo dos parâmetros n1 e n2.

O atributo xsi:type contem o valor xsd:int, onde xsd:int é um tipo de dados importado de XML Schema.


Este atributo xsi:type toma particular interesse no caso de linguagens de programação que não suportam WSDL, uma vez que esta última já especifica toda a API de um serviço Web, permitindo saber qual a natureza dos dados com que estamos a trabalhar. Para mais pormenores sobre a WSDL consulte o Capítulo ???.

Os tipos de dados simples no SOAP são os mesmos que se encontram definidos no XML Schema, ou então são derivados desses, sendo sempre representados, no corpo da mensagem SOAP, como elementos individuais.

Uma vez que a exposição dos tipos de dados do XML Schema é feita noutra secção, ???, vamos ver como utilizar dados de tipos mais estruturados.

2.2. Tipos estruturados

Mais à frente, iremos ver com detalhe como são suportados estes tipos de informação na implementação de serviços. Para já, vamos ver como são representados a nível das mensagens SOAP que se vão trocando.

Comecemos por ver como são suportados os arrays.

2.2.1. Arrays

Para enviar ou receber um array numa mensagem SOAP é necessário indicar o seu tamanho e o tipo dos seus elementos.

Para criar um array é necessário recorrer ao atributo arrayType, o qual permite especificar a dimensão do array e o tipo de dados dos diversos elementos que o compõem, e definir o atributo xsi:type como sendo do tipo Array.

Parece confuso, mas na realidade o conceito de array numa mensagem SOAP é bastante simples, não sendo mais do que uma lista. Como nada melhor que um exemplo para clarificar as possíveis dúvidas, peguemos mais num exemplo aritmético muito simples: uma lista de inteiros.

Exemplo 1.5. Representação em SOAP de um array

Neste exemplo, mostra-se uma mensagem SOAP que correponde a um pedido para somar uma lista de inteiros que é enviada no corpo da mensagem.

POST /nusoap-0.9.5/SOAP-arrays/serv-listas.php HTTP/1.0
Host: localhost:8888
User-Agent: NuSOAP/0.9.5 (1.123)
Content-Type: text/xml; charset=ISO-8859-1
SOAPAction: "uri:ws.di.uminho.pt/Listas/somaLista"
Content-Length: 708

<?xml version="1.0" encoding="ISO-8859-1"?>
<SOAP-ENV:Envelope 
    SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
  <SOAP-ENV:Body>
    <ns1137:somaLista xmlns:ns1137="uri:ws.di.uminho.pt/Listas">     1
      <n1 xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:int[5]"> 2
        <item xsi:type="xsd:int">1</item>                           3
        <item xsi:type="xsd:int">2</item>
        <item xsi:type="xsd:int">3</item>
        <item xsi:type="xsd:int">4</item>
        <item xsi:type="xsd:int">5</item>
      </n1>
    </ns1137:somaLista>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

1

Indicação do método que se está a invocar: somaLista;

2

No caso de listas, indica-se no atributo xsi:type que se está a enviar um array, SOAP-ENC:Array, e no atributo SOAP-ENC:arrayType a dimensão da lista, neste caso 5, e o tipo dos seus elementos, neste caso xsd:int;

3

É acrescentado um subelemento item para cada elemento da lista, com o respetivo atributo xsi:type.


2.2.2. Produto cartesiano (structs)

Outro tipo estruturado de dados muito frequente é o produto cartesiano, ou por outras palavras, o registo de dados.

Em muitas linguagens de programação o produto cartesiano é tratado como uma lista em que, na maior parte dos casos, o tipo dos seus elementos é heterogéneo.

Vamos exemplificar novamente com um exemplo muito simples, um serviço a quem é enviado um registo de aluno composto por um nome e uma nota e que devolve a nota desse aluno.

Exemplo 1.6. Representação em SOAP de um produto cartesiano

POST /nusoap-0.9.5/SOAP-structs/serv-structs.php HTTP/1.0
Host: localhost:8888
User-Agent: NuSOAP/0.9.5 (1.123)
Content-Type: text/xml; charset=ISO-8859-1
SOAPAction: "uri:ws.di.uminho.pt/Estruturas/nota"
Content-Length: 549

<?xml version="1.0" encoding="ISO-8859-1"?>
<SOAP-ENV:Envelope 
    SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
  <SOAP-ENV:Body>
    <ns4500:nota xmlns:ns4500="uri:ws.di.uminho.pt/Estruturas"> 1
      <l>                                                       2
        <nome xsi:type="xsd:string">Ana</nome>                 3
        <nota xsi:type="xsd:int">13</nota>                     4
      </l>
    </ns4500:nota>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

1

Invocação do método nota;

2

Este elemento marca o início do parâmetro l;

3

Este subelemento do parâmetro contem o campo nome do aluno;

4

Este subelemento do parâmetro contem o campo nota do aluno;

Como se pode ver pelo exemplo, o parâmetro do método serviu de contentor para o produto cartesiano e cada campo deste aparece como sublemento do parâmetro devidamente tipado com o tipo simples aplicável.


2.2.3. Listas de estruturas

A partir do momento em que o SOAP nos permite representar tipos simples, listas e produto cartesiano é virtualmente possível representar qualquer estrutura de dados por mais complexa que seja.

Como último exemplo, vamos mostrar uma mensagem SOAP correspondente a um pedido de cálculo da nota máxima numa lista de alunos, ou seja, iremos passar como parâmetro ao serviço uma lista de registos de aluno e como resultado o serviço devolve-nos o registo do aluno com a nota mais alta.

Exemplo 1.7. Representação em SOAP de uma lista de estruturas

...
  <ns6271:notaMaisAlta xmlns:ns6271="uri:ws.di.uminho.pt/Estruturas">
      <l xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="unnamed_struct_use_soapval[3]">
          <item>
              <nome xsi:type="xsd:string">Ana</nome>
              <nota xsi:type="xsd:int">13</nota>
          </item>
          <item>
              <nome xsi:type="xsd:string">Carlos</nome>
              <nota xsi:type="xsd:int">15</nota>
          </item>
          <item>
              <nome xsi:type="xsd:string">Rui</nome>
              <nota xsi:type="xsd:int">14</nota>
          </item>
      </l>
  </ns6271:notaMaisAlta>
...

Repare no valor do atributo SOAP-ENC:arrayType. O valor unnamed_struct_use_soapval[3] indica que estamos perante uma lista de registos.


Compliquemos um pouco o exemplo apresentado anteriormente. O aluno em lugar de ter uma nota tem uma lista de notas e suponhamos que temos um serviço que nos devolve o aluno com a média mais alta. O pedido SOAP a invocar esse serviço mostra-se a seguir.

Exemplo 1.8. Representação em SOAP de estruturas aninhadas

...
<ns5152:mediaMaisAlta xmlns:ns5152="uri:ws.di.uminho.pt/Estruturas">
    <l xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="unnamed_struct_use_soapval[3]"> 1
        <item>          2
            <nome xsi:type="xsd:string">Ana</nome>
            <notas xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:int[3]"> 3
                <item xsi:type="xsd:int">13</item>
                <item xsi:type="xsd:int">14</item>
                <item xsi:type="xsd:int">15</item>
            </notas>
        </item>
        <item>
            <nome xsi:type="xsd:string">Carlos</nome>
            <notas xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:int[3]">
                <item xsi:type="xsd:int">11</item>
                <item xsi:type="xsd:int">15</item>
                <item xsi:type="xsd:int">12</item>
            </notas>
        </item>
        <item>
            <nome xsi:type="xsd:string">Rui</nome>
            <notas xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:int[3]">
                <item xsi:type="xsd:int">12</item>
                <item xsi:type="xsd:int">12</item>
                <item xsi:type="xsd:int">14</item>
            </notas>
        </item>
    </l>
</ns5152:mediaMaisAlta>
...

1

O nosso parâmetro l é uma lista de 3 registos: unnamed_struct_use_soapval[3];

2

Para cada aluno, é gerado um elemento contentor, item devidamente tipado.

3

As notas de um aluno correspondem por sua vez a uma lista homogénea, neste caso, de inteiros: arrayType="xsd:int[3]";


Dos exemplos testados e expostos podemos concluir que qualquer estrutura composta por uma qualquer combinação de arrays, produto cartesiano e tipos simples pode ser codificada numa mensagem SOAP. Mais à frente iremos ver vários casos de estudo que implementam as ideias aqui exemplificadas.