Complex datatypes can be defined using XMLSchema and represented by WSDL. Any of the declared types may be used as arguments and return types of Virtuoso/PL procedures. Any procedures can thus be exposed as SOAP methods.

Complex data type definitions are used for values that cannot be contained by simple scalar datatypes. Typical examples are arrays of scalars, structures of scalars, arrays of structures or structures of arrays. A complex datatype may contain scalar and complex datatypes. When a complex type is used in the definition of another complex type, the definition of the contained complex type must exist.

In addition to 'usual' complex types as structures and arrays Virtuoso implements support for 'choice', 'enumeration', anyType and anyElement and extensions to the simple types. Inheritance of complex types is also possible and is discussed further in next chapter.

The 'nillable' and 'minOccurs' attributes in schema definitions have special meaning for PL values returned by PL procedure via SOAP. If this attribute is 'true' then output of NULL values will be serialized in their XML form with XMLSchema instance attribute 'nil' as 'true'. Otherwise if elements have 'minOccurs' equal to 0 (zero), the element will be omitted. If minOccurs is equal to 1 (one) an empty element will be sent to the client. The same algorithm applies to the serialization of PL values passed as parameters to soap_client() function. Therefore it's important to make proper use of these attributes when defining complex structures.

The '__VOID__' string constant has a special meaning in XMLSchema Datatypes. It is used to designate no output for return value. In other words returned value from PL procedure will not be serialized nor exposed in the WSDL file.

You define complex datatypes using soap_dt_define() . The function accepts a schema definition excerpt, based on the element complexType . The definition must be a valid XML document.

Example 17.1. Declaring and using complex datatypes in SOAP

In this example we define two complex datatypes. The first one, SOAPStruct , consists of scalars; the second one, ArrayOfSOAPStruct , is an array of these structures. These schema excerpts are stored in the filesystem as struct.xsd and array.xsd .

struct.xsd:


<!-- a SOAPStruct type declaration
     file name: struct.xsd -->

<complexType name="SOAPStruct"
   targetNamespace="http://tempuri.tmp/"
   xmlns:enc="http://schemas.xmlsoap.org/soap/encoding/"
   xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
   xmlns="http://www.w3.org/2001/XMLSchema"
   xmlns:tns="services.wsdl">

   <sequence>
     <element name="varString" type="string" nillable="true"/>
     <element name="varInt" type="int" nillable="true"/>
     <element name="varFloat" type="float" nillable="true"/>
   </sequence>
</complexType>

array.xsd:


<!-- array of SOAPStruct
     file name: array.xsd -->

<complexType name="ArrayOfSOAPStruct"
   targetNamespace="http://tempuri.tmp/"
   xmlns:enc="http://schemas.xmlsoap.org/soap/encoding/"
   xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
   xmlns="http://www.w3.org/2001/XMLSchema"
   xmlns:tns="services.wsdl">

   <complexContent>
   <restriction base="enc:Array">
   <sequence>
   <element name="item" type="tns:SOAPStruct" minOccurs="0" maxOccurs="unbounded"/>
   </sequence>
   <attribute ref="enc:arrayType" wsdl:arrayType="tns:SOAPStruct[]"/>
   <attributeGroup ref="enc:commonAttributes"/>
   <attribute ref="enc:offset"/>
   </restriction>
   </complexContent>
</complexType>

Next, we issue commands to define a new complex datatype. Correct order is important. (SQL> is the prompt of the Interactive SQL utility included with Virtuoso and should not be typed)

SQL> DB..soap_dt_define ('SOAPStruct', file_to_string ('struct.xsd'));
SQL> DB..soap_dt_define ('ArrayOfSOAPStruct', file_to_string ('array.xsd'));

[Note] Note:

The WSDL specification requires that array names be prefixed with ArrayOf .