Simon Fell > Its just code > Handling Arrays of Complex Types in PocketSOAP

Monday, June 7, 2004

A popular question recently, you have 2 choices, (1) go grab the WSDL Wizard and have it generate all the code for you or (2) follow this example.

This quick demo will call a method from the SOAPBuilders Interop tests called echoStructArray, this method takes an array of structures (aka ComplexTypes) as input and echos the array back as output (see the WSDL for the details. By default, an array of complex types is going to be represented in PocketSOAP as an array of CoSoapNode objects, each Node object will have child nodes in the Nodes property containing the child elements. So to create an array of complex types, we need to declare the array, then populate each array item with a CoSoapNode object, e.g.

    Dim arr(2) As Object
    Set arr(0) = makeSoapStruct("String one", 1, 1.1)
    Set arr(1) = makeSoapStruct("String two", 2, 2.2)
    Set arr(2) = makeSoapStruct("String three", 3, 3.3)

Where makeSoapStruct is defined as

' helper function to create a SOAPStruct complex type
Private Function makeSoapStruct(varString As String, varInt As Long, varFloat As Single) As CoSoapNode
    Dim ct As New CoSoapNode
    ct.Nodes.Create "varString", varString
    ct.Nodes.Create "varInt", varInt
    ct.Nodes.Create "varFloat", varFloat
    Set makeSoapStruct = ct
End Function

To handle the response, its just the reverse, grab the parameter, its value will be an array of variants, each variant will contain a CoSoapNode object, e.g.

    'get the returned array
    Dim res()
    res = e.Parameters.Item(0).Value
    ' iterate over it
    Dim idx As Integer
    Dim n As CoSoapNode
    For idx = LBound(res) To UBound(res)
        ' each item in the array is a soapnode, with child nodes for varString, varInt, varFloat
        Set n = res(idx)
        List1.AddItem n.Nodes.ItemByName("varString").Value & " " & n.Nodes.ItemByName("varInt").Value & " " & n.Nodes.ItemByName("varFloat").Value

That's all there is to it!. The full VB code is available for download (2k), for reference, these are the generated request and response messages from this code.

Accept-Charset: UTF-8, UTF-16;q=0.8, iso-8859-1;q=0.8
Accept-Encoding: deflate, gzip
Content-Type: text/xml; charset=UTF-8
SOAPAction: ""
User-Agent: PocketSOAP/1.5.b1/PocketHTTP/1.2
Content-Length: 1209

  <a:echoStructArray S:encodingStyle="">
    <inputStructArray XI:type="Enc:Array" Enc:arrayType="XS:anyType[3]">
      <x href="#3dd43e4"/>
      <x href="#3ddd48c"/>
      <x href="#3dd42bc"/>
   <x S:encodingStyle="" Enc:root="0" id="3dd42bc">
    <varString XI:type="XS:string">String three</varString>
    <varInt XI:type="XS:int">3</varInt>
    <varFloat XI:type="XS:float">3.3</varFloat>
   <x S:encodingStyle="" Enc:root="0" id="3ddd48c">
    <varString XI:type="XS:string">String two</varString>
    <varInt XI:type="XS:int">2</varInt>
    <varFloat XI:type="XS:float">2.2</varFloat>
   <x S:encodingStyle="" Enc:root="0" id="3dd43e4">
    <varString XI:type="XS:string">String one</varString>
    <varInt XI:type="XS:int">1</varInt>
    <varFloat XI:type="XS:float">1.1</varFloat>
HTTP/1.1 200 OK
Date: Tue, 08 Jun 2004 03:23:52 GMT
Server: Microsoft-IIS/5.0
Content-Length: 1175
Content-Type: text/xml; charset=UTF-8
Expires: Tue, 08 Jun 2004 03:23:52 GMT
Cache-control: private
X-Cache: MISS from

<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV=""
    xmlns:xsi=""     SOAP-ENV:encodingStyle="">
  <m:echoStructArrayResponse xmlns:m="">
   <outputStructArray xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="ns1:SOAPStruct[3]" xmlns:ns1="">
    <SOAPStruct xsi:type="ns1:SOAPStruct">
     <varString xsi:type="xsd:string">String one</varString>
     <varInt xsi:type="xsd:int">1</varInt>
     <varFloat xsi:type="xsd:float">1.1</varFloat>
    <SOAPStruct xsi:type="ns1:SOAPStruct">
     <varString xsi:type="xsd:string">String two</varString>
     <varInt xsi:type="xsd:int">2</varInt>
     <varFloat xsi:type="xsd:float">2.2</varFloat>
    <SOAPStruct xsi:type="ns1:SOAPStruct">
     <varString xsi:type="xsd:string">String three</varString>
     <varInt xsi:type="xsd:int">3</varInt>
     <varFloat xsi:type="xsd:float">3.3</varFloat>