gSOAP 2.7.9 User Guide

gSOAP 2.7.9 User Guide

Robert van Engelen
Florida State University
and Genivia, Inc.
engelen@genivia.com & engelen@acm.org

Sep 26, 2007
[This document is also available in PDF format (black and white only)]



Contents

Introduction
    1.1  Getting Started
    1.2  Your First Web Service Client Application
    1.3  Your First Web Service in CGI
    1.4  Features
Notational Conventions
Differences Between gSOAP Versions 2.4 (and Earlier) and 2.5
Differences Between gSOAP Versions 2.1 (and Earlier) and 2.2
Differences Between gSOAP Versions 1.X and 2.X
Interoperability
Quick User Guide
    7.1  How to Use the gSOAP Stub and Skeleton Compiler to Build SOAP Clients
        7.1.1  Example
        7.1.2  Namespace Considerations
        7.1.3  Example
        7.1.4  How to Generate C++ Client Proxy Classes
        7.1.5  XSD Type Encoding Considerations
        7.1.6  Example
        7.1.7  How to Change the Response Element Name
        7.1.8  Example
        7.1.9  How to Specify Multiple Output Parameters
        7.1.10  Example
        7.1.11  How to Specify Output Parameters With struct/class Compound Data Types
        7.1.12  Example
        7.1.13  How to Specify Anonymous Parameter Names
        7.1.14  How to Specify a Method with No Input Parameters
        7.1.15  How to Specify a Method with No Output Parameters
    7.2  How to Use the gSOAP Stub and Skeleton Compiler to Build SOAP Web Services
        7.2.1  Example
        7.2.2  MSVC++ Builds
        7.2.3  How to Create a Stand-Alone gSOAP Service
        7.2.4  How to Create a Multi-Threaded Stand-Alone Service
        7.2.5  How to Pass Application Data to Service Methods
        7.2.6  Some Web Service Implementation Issues
        7.2.7  How to Generate C++ Server Object Classes
        7.2.8  How to Generate WSDL Service Descriptions
        7.2.9  Example
        7.2.10  How to Parse and Import WSDL Service Descriptions to Develop Clients and Servers
        7.2.11  The typemap.dat File
        7.2.12  How to Use Client Functionalities Within a Service
    7.3  How to Use gSOAP for Asynchronous One-Way Message Passing
    7.4  One-Way Message Passing over HTTP
    7.5  How to Use the SOAP Serializers and Deserializers to Save and Load Application Data
        7.5.1  Serializing a Data Type
        7.5.2  Deserializing a Data Type
        7.5.3  Example
        7.5.4  Serializing and Deserializing Class Instances to Streams
        7.5.5  How to Specify Default Values for Omitted Data
Using the gSOAP Stub and Skeleton Compiler
    8.1  Compiler Options
    8.2  SOAP 1.1 Versus SOAP 1.2
    8.3  The soapdefs.h Header File
    8.4  How to Build Modules and Libraries with the gSOAP #module Directive
    8.5  How to use the gSOAP #import Directive
    8.6  How to Use #include and #define Directives
    8.7  Compiling a gSOAP Client
    8.8  Compiling a gSOAP Web Service
    8.9  Using gSOAP for Creating Web Services and Clients in Pure C
    8.10  Limitations of gSOAP
    8.11  Compile Time Flags
    8.12  Run Time Flags
    8.13  Memory Management
        8.13.1  Memory Management Policies
        8.13.2  Intra-Class Memory Management
    8.14  Debugging
    8.15  Required Libraries
The gSOAP Remote Method Specification Format
    9.1  Remote Method Parameter Passing
    9.2  Error Codes
    9.3  C/C++ Identifier Name to XML Name Translations
    9.4  Namespace Mapping Table
10  gSOAP Serialization and Deserialization Rules
    10.1  SOAP RPC Encoding Versus Document/Literal and xsi:type Info
    10.2  Primitive Type Encoding
    10.3  How to Encode and Decode Primitive Types as XSD Types
        10.3.1  How to Use Multiple C/C++ Types for a Single Primitive XSD Type
        10.3.2  How to use Wrapper Classes to Specify Polymorphic Primitive Types
        10.3.3  XSD Schema Type Decoding Rules
        10.3.4  Multi-Reference Strings
        10.3.5  "Smart String" Mixed-Content Decoding
        10.3.6  STL Strings
        10.3.7  Changing the Encoding Precision of float and double Types
        10.3.8  INF, -INF, and NaN Values of float and double Types
    10.4  Enumeration Serialization
        10.4.1  Serialization of Symbolic Enumeration Constants
        10.4.2  Encoding of Enumeration Constants
        10.4.3  Initialized Enumeration Constants
        10.4.4  How to "Reuse" Symbolic Enumeration Constants
        10.4.5  Boolean Enumeration Serialization for C
        10.4.6  Bitmask Enumeration Serialization
    10.5  Struct Serialization
    10.6  Class Instance Serialization
        10.6.1  Example
        10.6.2  Initialized static const Fields
        10.6.3  Class Methods
        10.6.4  Getter and Setter Methods
        10.6.5  Streaming XML with Getter and Setter Methods
        10.6.6  Polymorphism, Derived Classes, and Dynamic Binding
        10.6.7  XML Attributes
        10.6.8  QName Attributes and Elements
    10.7  Union Serialization
    10.8  Serializing Pointer Types
        10.8.1  Multi-Referenced Data
        10.8.2  NULL Pointers and Nil Elements
    10.9  Void Pointers
    10.10  Fixed-Size Arrays
    10.11  Dynamic Arrays
        10.11.1  SOAP Array Bounds Limits
        10.11.2  One-Dimensional Dynamic Arrays
        10.11.3  Example
        10.11.4  One-Dimensional Dynamic Arrays With Non-Zero Offset
        10.11.5  Nested One-Dimensional Dynamic Arrays
        10.11.6  Multi-Dimensional Dynamic Arrays
        10.11.7  Encoding XML Generics Containing Dynamic Arrays
        10.11.8  STL Containers
        10.11.9  Polymorphic Dynamic Arrays and Lists
        10.11.10  How to Change the Tag Names of the Elements of a SOAP Array or List
    10.12  Base64Binary XML Schema Type Encoding
    10.13  hexBinary XML Schema Type Encoding
    10.14  Literal XML Encoding Style
        10.14.1  Serializing and Deserializing Mixed Content XML With Strings
11  SOAP Fault Processing
12  SOAP Header Processing
13  MIME Attachments
    13.1  Sending a Collection of MIME Attachments (SwA)
    13.2  Retrieving a Collection of MIME Attachments (SwA)
14  DIME Attachments
    14.1  Sending a Collection of DIME Attachments
    14.2  Retrieving a Collection of DIME Attachments
    14.3  Serializing Binary Data in DIME
    14.4  Streaming DIME
    14.5  Streaming Chunked DIME
    14.6  WSDL Bindings for DIME Attachments
15  MTOM Attachments
    15.1  Generating MultipartRelated MIME Attachment Bindings in WSDL
    15.2  Sending and Receiving MTOM Attachments
    15.3  Streaming MTOM/MIME
    15.4  Redirecting Inbound MTOM/MIME Streams Based on SOAP Body Content
    15.5  Streaming Chunked MTOM/MIME
16  XML Validation
    16.1  Occurrence Constraints
        16.1.1  Elements with minOccurs and maxOccurs Restrictions
        16.1.2  Required and Prohibited Attributes
        16.1.3  Data Length Restrictions
    16.2  Other Constraints
17  SOAP-over-UDP
    17.1  Using WS-Addressing with SOAP-over-UDP
    17.2  Client-side One-way Unicast
    17.3  Client-side One-way Multicast
    17.4  Client-side Request-Response Unicast
    17.5  Client-side Request-Response Multicast
    17.6  SOAP-over-UDP Server
18  Advanced Features
    18.1  Internationalization
    18.2  Customizing the WSDL and Namespace Mapping Table File Contents With gSOAP Directives
        18.2.1  Example
    18.3  Transient Data Types
    18.4  Volatile Data Types
    18.5  How to Declare User-Defined Serializers and Deserializers
    18.6  How to Serialize Data Without Generating XSD Type Attributes
    18.7  Function Callbacks for Customized I/O and HTTP Handling
    18.8  HTTP 1.0 and 1.1
    18.9  HTTP 307 Temporary Redirect Support
    18.10  HTTP GET Support
    18.11  TCP and HTTP Keep-Alive
    18.12  HTTP Chunked Transfer Encoding
    18.13  HTTP Buffered Sends
    18.14  HTTP Authentication
    18.15  HTTP Proxy Authentication
    18.16  Speed Improvement Tips
    18.17  Timeout Management for Non-Blocking Operations
    18.18  Socket Options and Flags
    18.19  Secure SOAP Web Services with HTTPS/SSL
    18.20  Secure SOAP Clients with HTTPS/SSL
    18.21  SSL Authentication Callback
    18.22  SSL Certificates
    18.23  SSL Hardware Acceleration
    18.24  SSL on Windows
    18.25  Zlib Compression
    18.26  Client-Side Cookie Support
    18.27  Server-Side Cookie Support
    18.28  Connecting Clients Through Proxy Servers
    18.29  FastCGI Support
    18.30  How to Create gSOAP Applications With a Small Memory Footprint
    18.31  How to Eliminate BSD Socket Library Linkage
    18.32  How to Combine Multiple Client and Server Implementations into one Executable
    18.33  How to Build a Client or Server in a C++ Code Namespace
    18.34  How to Create Client/Server Libraries
        18.34.1  C++ Example
        18.34.2  C Example
    18.35  How to Create DLLs
        18.35.1  Create the Base stdsoap2.dll
        18.35.2  Creating Client and Server DLLs
    18.36  gSOAP Plug-ins
        18.36.1  The Message Logging and Statistics Plug-in
        18.36.2  The HTTP GET Plug-in
        18.36.3  The HTTP MD5 Plug-in
        18.36.4  The HTTP Digest Authentication Plug-in
        18.36.5  The WS-Addressing Plug-in
        18.36.6  The WS-Security Plug-in

Copyright (C) 2000-2006 Robert A. van Engelen, Genivia, Inc., All Rights Reserved.

1  Introduction

The gSOAP tools provide a SOAP/XML-to-C/C++ language binding to ease the development of SOAP/XML Web services and client application in C and C++. Most toolkits for C++ Web services adopt a SOAP-centric view and offer APIs that require the use of class libraries for SOAP-specific data structures. This often forces a user to adapt the application logic to these libraries. In contrast, gSOAP provides a C/C++ transparent SOAP API through the use of compiler technology that hides irrelevant SOAP-specific details from the user. The gSOAP stub and skeleton compiler automatically maps native and user-defined C and C++ data types to semantically equivalent XML data types and vice-versa. As a result, full SOAP interoperability is achieved with a simple API relieving the user from the burden of SOAP details, thus enabling him or her to concentrate on the application-essential logic.
The gSOAP compiler enables the integration of (legacy) C/C++ and Fortran codes (through a Fortran to C interface), embedded systems, and real-time software in SOAP applications that share computational resources and information with other SOAP applications, possibly across different platforms, language environments, and disparate organizations located behind firewalls.

1.1  Getting Started

To start building Web services applications with gSOAP, you need: gSOAP is self-contained, so there is no need to download any third-party software (unless you want to use OpenSSL and the library is not already installed).
Although gSOAP is available in binary format for several platforms, the code generated by the gSOAP stub and skeleton compiler and the gSOAP runtime codes are equivalent. This means that the generated codes can be transferred to other platforms and compiled.
The gSOAP packages available from SourceForge include pre-build tools: Win32 versions of these two are included in the Win32 gSOAP package only. If you don't have the binaries or if you want to rebuild them, you need Bison and Flex are preferred.
The tools are used to generate code that is linked with the gSOAP engine soapcpp2.c (C version) or soapcpp2.cpp (C++ version) and your application code. The engine is also available as a library libgsoap.a and libgsoap++.a with separate versions that support SSL. See the README.txt instructions on how to build these libraries with the platform-independent gSOAP package's autoconf and automake.
The gSOAP packages contain numerous examples in the samples directory. Run make to build the example applications. The examples are also meant to demonstrate different features of gSOAP. The simplest examples are the one-liners in samples/oneliners. Indeed, you can write a one-line Web service with CGI!. A streaming DIME attachment server and client application demonstrate efficient file exchanges in samples/dime. An SSL-secure Web server application demonstrates the generation of dynamic content for Web browsing and Web services functionality at the same time, see samples/webservice. And much more.

1.2  Your First Web Service Client Application

The gSOAP tools minimize application adaptation efforts for building Web Services. The gSOAP wsdl2h tool imports one or more WSDLs and XML schemas to generate a header file with the Web service operations and the C/C++ data types used by the services. The gSOAP soapcpp2 compiler takes the header file and generates XML serializers for the data types (soapH.h and soapC.cpp), the client-side stubs (soapClient.cpp), and server-side skeletons (soapServer.cpp).
The gSOAP soapcpp2 compiler can also generate WSDL definitions for implementing a service from scratch, i.e. without defining a WSDL first. This "closes the circle" in that it enables Web services development from WSDL or directly from a set op C/C++ operations in a header file without the need for users to analyze Web service details.
You only need to follow a few steps to execute the tools from the command line or Makefile (see also MSVC++ project examples in the samples directory with tool integration in the MSVC++ IDE). For example, to generate code for the XMethods service listing Web service, we run the wsdl2h tool from the command line on the URL of the WSDL and use option -o to specify the output file:

$ wsdl2h -o XMethodsQuery.h http://www.xmethods.net/wsdl/query.wsdl

This generates the XMethodsQuery.h header file with Web service operations and the data types that the service uses. This header file is to be processed with soapcpp2 to generate the stub and/or skeleton code. The XMethodsQuery.h file includes all documentation, so you can use Doxygen (http://www.doxygen.org) to automatically generate the documentation pages for your development.
In this example we are developing a C++ API for the XMethods service. By default, gSOAP assumes you will use C++ with STL. To build without STL, use option -s:

$ wsdl2h -s -o XMethodsQuery.h http://www.xmethods.net/wsdl/query.wsdl

To build a pure C application, use option -c:

$ wsdl2h -c -o XMethodsQuery.h http://www.xmethods.net/wsdl/query.wsdl

We have not yet generated the stubs for the C/C++ API. To do so, run the soapcpp2 compiler:

$ soapcpp2 -C -Iimport XMethodsQuery.h

Where option -C indicates client-side only files (soapcpp2 generates both client and server stubs and skeletons by default). Option -I is needed to import the stlvector.h file to support STL vectors.
Suppose we develop a C++ client for the XMethods service. In this case we use the generated soapXMethodsQuerySoapProxy class and XMethodsQuerySoap.nsmap XML namespace mapping table to access the Web service. The soapXMethodsQuerySoapProxy class is a proxy to invoke the service:

#include "soapXMethodsQuerySoapProxy.h"
#include "XMethodsQuerySoap.nsmap"
main()
{
   XMethodsQuerySoap service;
   ns3__getAllServiceNamesResponse response;
   // get all service names from the XMethods database:
   if (service.ns3__getAllServiceNames(response) == SOAP_OK)
      std::cout << "The first XMethods service is: " << (*response._Result->__ptr[0]->name) << std::endl;
   else
      soap_print_fault(service.soap, stderr);
}

The response data structure is defined in XMethodsQuery.h, and contains a SOAP encoded array (__ptr[n]) of pointers to ID-Name pairs (__ptr[n]->id and __ptr[n]->name). (Note: you may want to add NULL checks before dereferencing the pointers.) To complete the build, compile and link the generated soapC.cpp, soapClient.cpp, and the run-time gSOAP engine stdsoap2.cpp with your code.

1.3  Your First Web Service in CGI

Developing a service application is easy too.
Suppose we implement a CGI-based service that returns the time in GMT. The Common Gateway Interface (CGI) is a simple mechanism to publish services on your Web site, but it is certainly not the most efficient way. You can also develop high-performance stand-alone gSOAP services with built-in HTTP/S stacks or you can use Apache mod_gsoap and IIS (see the extras directory).
Our currentTime service only has an output parameter, which is the current time:

// File: currentTime.h
//gsoap ns service name: currentTime
//gsoap ns service namespace: urn:currentTime
//gsoap ns service location: http://www.yourdomain.com/currentTime.cgi
int ns__currentTime(time_t& response);

Note that we must associate an XML namespace with a service. The gSOAP tools use a special convention for identifier names that are part of a namespace: a namespace prefix (ns in this case) followed by a double underscore __. This convention is used to resolve namespaces and to avoid name clashes. The ns namespace prefix is bound to the urn:currentTime namespace name with the //gsoap directive. The //gsoap directives are used to set the properties of the service, in this case the name, namespace, and location endpoint.
The service implementation for CGI is

// File: currentTime.cpp
main()
{
   // create soap context and serve one CGI-based request:
   soap_serve(soap_new());
}
int ns__currentTime(struct soap *soap, time_t& response)
{
   response = time(0);
   return SOAP_OK;
}

Note that we pass the soap struct with the gSOAP context information to the service routine, which can be handy to determine properties of the connection and to dynamically allocate data with soap_malloc(soap, num_bytes) that will be automatically deleted when the service is finished. We run the soapcpp2 compiler on the header file to generate the server-side code:

$ soapcpp2 -S currentTime.h

and then compile the CGI binary:

$ c++ -o currentTime.cgi currentTime.cpp soapC.cpp soapServer.cpp stdsoap2.cpp

To activate the service, copy the currentTime.cgi binary to your bin-cgi directory with the proper file permissions.
The soapcpp2 compiler generated the WSDL definitions currentTime.wsdl. You can use the WSDL to advertize your service. You don't need to use this WSDL to develop a gSOAP client. You can use the currentTime.h file with the soapcpp2 -C command to generate client-side code.
When you contribute a Web service with interesting capabilities, you can contact www.XMethods.com to publish your service and see it with the client application for the XMethods service listing you developed in the previous section.

1.4  Features

The highlights of gSOAP are:

2  Notational Conventions

The typographical conventions used by this document are:
Sans serif or italics font
denotes C and C++ source code, file names, and shell/batch commands.
Bold font
denotes C and C++ keywords.
Courier font
denotes HTTP header content, HTML, XML, XML Schema content and WSDL content.
[Optional]
denotes an optional construct.
The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC-2119.

3  Differences Between gSOAP Versions 2.4 (and Earlier) and 2.5

To comply with WS-I Basic Profile 1.0a, gSOAP 2.5 and higher adopts SOAP document/literal by default. There is no need for concern, because the WSDL parser wsdl2h automatically takes care of the differences when you provide a WSDL document, because SOAP RPC encoding, literal, and document style are supported. A new soapcpp2 compiler option was added -e for backward compatibility with gSOAP 2.4 and earlier to adopt SOAP RPC encoding by default in case you want to develop a service that uses SOAP encoding. You can also use the gSOAP compiler directives to specify SOAP encoding for individual operarations, when desired.

4  Differences Between gSOAP Versions 2.1 (and Earlier) and 2.2

You should read this section only if you are upgrading from gSOAP 2.1 to 2.2 and later.
Run-time options and flags have been changed to enable separate recv/send settings for transport, content encodings, and mappings. The flags are divided into four classes: transport (IO), content encoding (ENC), XML marshalling (XML), and C/C++ data mapping (C). The old-style flags soap_disable_X and soap_enable_X, where X is a particular feature, are deprecated. See Section 8.12 for more details.

5  Differences Between gSOAP Versions 1.X and 2.X

You should read this section only if you are upgrading from gSOAP 1.X to 2.X.
gSOAP versions 2.0 and later have been rewritten based on versions 1.X. gSOAP 2.0 and later is thread-safe, while 1.X is not. All files in the gSOAP 2.X distribution are renamed to avoid confusion with gSOAP version 1.X files:

gSOAP 1.X gSOAP 2.X
soapcpp soapcpp2
soapcpp.exe soapcpp2.exe
stdsoap.h stdsoap2.h
stdsoap.c stdsoap2.c
stdsoap.cpp stdsoap2.cpp

Changing the version 1.X application codes to accommodate gSOAP 2.X does not require a significant amount of recoding. The change to gSOAP 2.X affects all functions defined in stdsoap2.c[pp] (the gSOAP runtime environment API) and the functions in the sources generated by the gSOAP compiler (the gSOAP RPC+marshalling API). Therefore, clients and services developed with gSOAP 1.X need to be modified to accommodate a change in the calling convention used in 2.X: In 2.X, all gSOAP functions (including the remote method proxy routines) take an additional parameter which is an instance of the gSOAP runtime environment that includes file descriptors, tables, buffers, and flags. This additional parameter is always the first parameter of any gSOAP function.
The gSOAP runtime environment is stored in a struct soap type. A struct was chosen to support application development in C without the need for a separate gSOAP implementation. An object-oriented approach with a class for the gSOAP runtime environment would have prohibited the implementation of pure C applications. Before a client can invoke remote methods or before a service can accept requests, a runtime environment need to be allocated and initialized. Three new functions are added to gSOAP 2.X:

Function Description
soap_init(struct soap *soap) Initializes a static or stack-allocated environment (required only once)
struct soap *soap_new() Allocates, initializes, and returns a pointer to a runtime environment
struct soap *soap_copy(struct soap *soap) Allocates a new runtime environment and copies contents of the environment such that the new environment does not share any data with the original environment

An environment can be reused as many times as necessary and does not need to be reinitialized in doing so. A dynamically allocated environment is deallocated with soap_free.
A new environment is only required for each new thread to guarantee exclusive access to a new runtime environment by each thread. For example, the following code stack-allocates the runtime environment which is used for multiple remote method calls:

int main()
{
   struct soap soap;
   ...
   soap_init(&soap); // initialize runtime environment
   ...
   soap_call_ns__method1(&soap, ...); // make a remote call
   ...
   soap_call_ns__method2(&soap, ...); // make another remote call
   ...
   soap_destroy(&soap); // remove deserialized class instances (C++ only)
   soap_end(&soap); // clean up and remove deserialized data
   soap_done(&soap); // detach environment (last use and no longer in scope)
   ...
}

The runtime environment can also be heap allocated:

int main()
{
   struct soap *soap;
   ...
   soap = soap_new(); // allocate and initialize runtime environment
   if (!soap) // couldn't allocate: stop
   ...
   soap_call_ns__method1(soap, ...); // make a remote call
   ...
   soap_call_ns__method2(soap, ...); // make another remote call
   ...
   soap_destroy(soap); // remove deserialized class instances (C++ only)
   soap_end(soap); // clean up and remove deserialized data
   soap_free(soap); // detach and free runtime environment
}

A service need to allocate and initialize an environment before calling soap_serve:

int main()
{
   struct soap soap;
   soap_init(&soap);
   soap_serve(&soap);
}

Or alternatively:

int main()
{
   soap_serve(soap_new());
}

The soap_serve dispatcher handles one request or multiple requests when HTTP keep-alive is enabled (with the SOAP_IO_KEEPALIVE flag see Section 18.11).
A service can use multi-threading to handle requests while running some other code that invokes remote methods:

int main()
{
   struct soap soap1, soap2;
   pthread_t tid;
   ...
   soap_init(&soap1);
   if (soap_bind(&soap1, host, port, backlog) < 0) exit(1);
   if (soap_accept(&soap1) < 0) exit(1);
   pthread_create(&tid, NULL, (void*(*)(void*))soap_serve, (void*)&soap1);
   ...
   soap_init(&soap2);
   soap_call_ns__method(&soap2, ...); // make a remote call
   ...
   soap_end(&soap2);
   ...
   pthread_join(tid, NULL); // wait for thread to terminate
   soap_end(&soap1); // release its data
}

In the example above, two runtime environments are required. In comparison, gSOAP 1.X statically allocates the runtime environment, which prohibits multi-threading (only one thread can invoke remote methods and/or accept requests due to the single runtime environment).
Section 7.2.4 presents a multi-threaded stand-alone Web Service that handles multiple SOAP requests by spawning a thread for each request.

6  Interoperability

gSOAP interoperability has been verified with the following SOAP implementations and toolkits:
Apache 2.2
Apache Axis
ASP.NET
Cape Connect
Delphi
easySOAP++
eSOAP
Frontier
GLUE
Iona XMLBus
kSOAP
MS SOAP
Phalanx
SIM
SOAP::Lite
SOAP4R
Spray
SQLData
Wasp Adv.
Wasp C++
White Mesa
xSOAP
ZSI
4S4C

7  Quick User Guide

This user guide offers a quick way to get started with gSOAP. This section requires a basic understanding of the SOAP 1.1 protocol and some familiarity with C and/or C++. In principle, SOAP clients and SOAP Web services can be developed in C and C++ with the gSOAP compiler without a detailed understanding of the SOAP protocol when gSOAP client-server applications are built as an ensamble and only communicate within this group (i.e. meaning that you don't have to worry about interoperability with other SOAP implementations). This section is intended to illustrate the implementation of gSOAP Web services and clients that connect to and interoperate with other SOAP implementations such as Apache Axis, SOAP::Lite, and .NET. This requires some details of the SOAP and WSDL protocols to be understood.

7.1  How to Use the gSOAP Stub and Skeleton Compiler to Build SOAP Clients

In general, the implementation of a SOAP client application requires a stub routine for each remote method that the client application needs to invoke. The primary stub's responsibility is to marshall the parameter data, send the request with the parameters to the designated SOAP service over the wire, to wait for the response, and to demarshall the parameter data of the response when it arrives. The client application invokes the stub routine for a remote method as if it would invoke a local method. To write a stub routine in C or C++ by hand is a tedious task, especially if the input and/or output parameters of a remote method contain elaborate data structures such as records, arrays, and graphs. Fortunately, the gSOAP 'wsdl2h' WSDL parser and 'soapcpp2' stub and skeleton compiler automate the development of Web service client and server applications.
The gSOAP stub and skeleton compiler is a preprocessor that generates the necessary C++ sources to build SOAP C++ clients. The input to the gSOAP stub and skeleton compiler consists of a standard C/C++ header file. The header file can be generated from a WSDL (Web Service Description Language) documentation of a service with the gSOAP WSDL parser.
Consider the following command (entered at the command prompt):

$ wsdl2h -o quote.h http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl

This generates the file quote.h in C++ format from the WSDL at the specified URL.
To generate a header file to develop a pure C client application, issue the command: Consider the following command (entered at the command prompt):

$ wsdl2h -c -o quote.h http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl

For more details on the WSDL parser and its options, see 7.2.10.
The quote.h header file is then processed by the gSOAP compiler to generate the stubs to develop client applications (and skeletons to develop a service).
The SOAP service methods are specified in the header file as function prototypes. Stub routines in C/C++ source form are automatically generated by the gSOAP compiler for these function prototypes of remote methods. The resulting stub routines allow C and C++ client applications to seamlessly interact with existing SOAP Web services.
The gSOAP stub and skeleton compiler also generates skeleton routines for each of the remote methods specified in the header file. The skeleton routines can be readily used to implement one or more of the remote methods in a new SOAP Web service. These skeleton routines are not used for building SOAP clients in C++, although they can be used to build mixed SOAP client/server applications (peer applications).
The input and output parameters of a SOAP service method may be simple data types or compound data types, either generated by the WSDL parser or specified by hand. The gSOAP stub and skeleton compiler automatically generates serializers and deserializers for the data types to enable the generated stub routines to encode and decode the contents of the parameters of the remote methods in XML.

7.1.1  Example

The getQuote remote method of XMethods Delayed Stock Quote service (defined in the quote.h file obtained with the 'wsdl2h' WSDL parser) provides a delayed stock quote for a given ticker name. The WSDL description of the XMethods Delayed Stock Quote service provides the following details:

Endpoint URL: http://services.xmethods.net:80/soap
SOAP action: "" (2 quotes)
Remote method namespace: urn:xmethods-delayed-quotes
Remote method name: getQuote
   Input parameter: symbol of type xsd:string
   Output parameter: Result of type xsd:float

The following getQuote.h header file for C is created from the WSDL description with the WSDL parser (the actual contents may vary depending on the 'wsdl2h' release version and the options used to determine the output):

//gsoap ns1 service name: net_DOTxmethods_DOTservices_DOTstockquote_DOTStockQuoteBinding
//gsoap ns1 service type: net_DOTxmethods_DOTservices_DOTstockquote_DOTStockQuotePortType
//gsoap ns1 service port: http://66.28.98.121:9090/soap
//gsoap ns1 service namespace: urn:xmethods-delayed-quotes
//gsoap ns1 service documentation: Definitions generated by the gSOAP WSDL parser 1.0
// Service net.xmethods.services.stockquote.StockQuoteService : net.xmethods.services.stockquote.StockQuote web service

//gsoap ns1 service method-style: getQuote rpc
//gsoap ns1 service method-encoding: getQuote http://schemas.xmlsoap.org/soap/encoding/
//gsoap ns1 service method-action: getQuote urn:xmethods-delayed-quotes#getQuote
int ns1__getQuote(char *symbol, float &Result);

The header file essentially specifies the service details in C/C++ with directives for the gSOAP compiler. The remote method is declared as a ns1__getQuote function prototype which specifies all of the necessary details for the gSOAP compiler to generate the stub routine for a client application to interact with the Delayed Stock Quote service.
The Delayed Stock Quote service description requires that the input parameter of the getQuote remote method is a symbol parameter of type string. The description also indicates that the Result output parameter is a floating point number that represents the current unit price of the stock in dollars. The gSOAP compiler uses the convention the last parameter of the function prototype must be the output parameter of the remote method, which is required to be passed by reference using the reference operator (&) or by using a pointer type. All other parameters except the last are input parameters of the remote method, which are required to be passed by value or passed using a pointer to a value (by reference is not allowed). The function prototype associated with a remote method is required to return an int, whose value indicates to the caller whether the connection to a SOAP Web service was successful or resulted in an exception, see Section 9.2 for the error codes.
The use of the namespace prefix ns1__ in the remote method name in the function prototype declaration is discussed in detail in 7.1.2. Basically, a namespace prefix is distinguished by a pair of underscores in the function name, as in ns1__getQuote where ns1 is the namespace prefix and getQuote is the remote method name. (A single underscore in an identifier name will be translated into a dash in XML, because dashes are more frequently used in XML compared to underscores, see Section 9.3.)
The gSOAP compiler is invoked from the command line with:

soapcpp2 getQuote.h

The compiler generates the stub routine for the getQuote remote method specified in the getQuote.h header file. This stub routine can be called by a client program at any time to request a stock quote from the Delayed Stock Quote service. The interface to the generated stub routine is the following function prototype generated by the gSOAP compiler:

int soap_call_ns1__getQuote(struct soap *soap, char *URL, char *action, char *symbol, float &Result);

The stub routine is saved in soapClient.cpp. The file soapC.cpp contains the serializer and deserializer routines for the data types used by the stub. You can use option -c for the soapcpp2 compiler to generate pure C code.
Note that the parameters of the soap_call_ns1__getQuote function are identical to the ns1__getQuote function prototype with three additional input parameters: soap must be a valid pointer to a gSOAP runtime environment, URL is the SOAP Web service endpoint URL passed as a string, and action is a string that denotes the SOAP action required by the Web service. Note that the XMethods Delayed Stock Quote service endpoint URL is http://66.28.98.121:9090/soap and the SOAP action required is "" (two quotes). You can change the endpoint and action dynamically. The endpoint and action are the second and third parameters of the soap_call_ns1__getQuote. When NULL, the values specified in the header file will be used.
The following example mixed C/C++ client program invokes the stub to retrieve the latest IBM stock quote from the XMethods Delayed Stock Quote service:

#include "soapH.h" // obtain the generated stub
#include "net_DOT_xmethods_DOT_services_DOT_stockquote_DOT_StockQuoteBinding.nsmap" // obtain the namespace mapping table
int main()
{
   struct soap soap; // gSOAP runtime environment
   float quote;
   soap_init(&soap); // initialize runtime environment (only once)
   if (soap_call_ns1__getQuote(&soap, NULL, NULL, "IBM", &quote) == SOAP_OK)
      std::cout << "Current IBM Stock Quote = " << quote << std::endl;
   else // an error occurred
      soap_print_fault(&soap, stderr); // display the SOAP fault message on the stderr stream
   soap_destroy(&soap); // delete deserialized class instances (for C++ only)
   soap_end(&soap); // remove deserialized data and clean up
   soap_done(&soap); // detach the gSOAP environment
   return 0;
}

When successful, the stub returns SOAP_OK and quote contains the latest stock quote. Otherwise, an error occurred and the SOAP fault is displayed with the soap_print_fault function. Use soap_sprint_fault(struct soap*, char *buf, size_t len) to print the error to a string.
The gSOAP compiler also generates a proxy class for C++ client applications. This generated proxy class can be included into a client application together with the generated namespace table as shown in this example:

#include "soapnet_DOT_xmethods_DOT_services_DOT_stockquote_DOT_StockQuoteBindingProxy.h" // get proxy
#include "net_DOT_xmethods_DOT_services_DOT_stockquote_DOT_StockQuoteBinding.nsmap" // obtain the namespace mapping table
int main()
{
   net q; // "net" is the proxy class with a name that is the short name of the service
   float r;
   if (q.ns1__getQuote("IBM", r) == SOAP_OK)
      std::cout << r << std::endl;
   else
      soap_print_fault(q.soap, stderr);
   return 0;
}

The proxy class constructor allocates and initializes a gSOAP environment for the instance. All the HTTP and SOAP/XML processing is hidden and performed on the background. Note that you can change the name of the service in the header file generated by the WSDL parser. The name is extracted from the WSDL content and may not always be in a short format. Feel free to change the entry

//gsoap ns1 service name: net_DOT_xmethods_DOT_services_DOT_stockquote_DOT_StockQuoteBinding

to use a more suitable name. The name will control the file name of the proxy class file and the XML namespace mapping table.
The following functions can be used to explicitly setup a gSOAP runtime environment (struct soap):

Function Description
soap_init(struct soap *soap) Initializes a static/stack-allocated runtime environment
soap_init1(struct soap *soap, soap_mode iomode) Initializes a runtime environment and set in/out mode flags
soap_init2(struct soap *soap, soap_mode imode, soap_mode omode) Initializes a runtime environment and set separate in/out mode flags
struct soap *soap_new() Allocates, initializes, and returns a pointer to a runtime environment
struct soap *soap_new1(soap_mode iomode) Allocates, initializes, and returns a pointer to a runtime environment and set in/out mode flags
struct soap *soap_new2(soap_mode imode, soap_mode omode) Allocates, initializes, and returns a pointer to a runtime environment and set separate in/out mode flags
struct soap *soap_copy(struct soap *soap) Allocates a new runtime environment and copies contents of the source environment such that the new environment does not share data with the source environment
soap_done(struct soap *soap) Reset, close communications, and remove callbacks
soap_free(struct soap *soap) Reset and deallocate the environment created with soap_new or soap_copy

An environment can be reused as many times as necessary for client-side remote calls and does not need to be reinitialized in doing so. A new environment is required for each new thread to guarantee exclusive access to runtime environments by threads. Also the use of any client calls within an active service method requires a new environment.
When the example client application is invoked, the SOAP request is performed by the stub routine soap_call_ns1__getQuote, which generates the following SOAP RPC request message:

POST /soap HTTP/1.1
Host: services.xmethods.net
Content-Type: text/xml
Content-Length: 529
SOAPAction: ""

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
   xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:ns1="urn:xmethods-delayed-quotes"
   SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:getQuote>
<symbol>IBM</symbol>
</ns1:getQuote>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

The XMethods Delayed Stock Quote service responds with the SOAP response message:

HTTP/1.1 200 OK
Date: Sat, 25 Aug 2001 19:28:59 GMT
Content-Type: text/xml
Server: Electric/1.0
Connection: Keep-Alive
Content-Length: 491

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
   soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/»
<soap:Body>
<n:getQuoteResponse xmlns:n="urn:xmethods-delayed-quotes»
<Result xsi:type="xsd:float»41.81</Result>
</n:getQuoteResponse>
</soap:Body>
</soap:Envelope>

The server's SOAP RPC response is parsed by the stub. The stub routine further demarshalls the data of Result element of the SOAP response and stores it in the quote parameter of soap_call_ns1__getQuote.
A client program can invoke a remote method at any time and multiple times if necessary. Consider for example:

...
struct soap soap;
float quotes[3]; char *myportfolio[] = {"IBM", "MSDN"};
soap_init(&soap); // need to initialize only once
for (int i = 0; i < 3; i++)
   if (soap_call_ns1__getQuote(&soap, "http://services.xmethods.net:80/soap", "", myportfolio[i], &quotes[i]) != SOAP_OK)
      break;
if (soap.error) // an error occurred
   soap_print_fault(&soap, stderr);
soap_end(&soap); // clean up all deserialized data
...

This client composes an array of stock quotes by calling the ns1__getQuote stub routine for each symbol in a portfolio array.
This example demonstrated how easy it is to build a SOAP client with gSOAP once the details of a Web service are available in the form of a WSDL document.

7.1.2  Namespace Considerations

The declaration of the ns1__getQuote function prototype (discussed in the previous section) uses the namespace prefix ns1__ of the remote method namespace, which is distinguished by a pair of underscores in the function name to separate the namespace prefix from the remote method name. The purpose of a namespace prefix is to associate a remote method name with a service in order to prevent naming conflicts, e.g. to distinguish identical remote method names used by different services.
Note that the XML response of the XMethods Delayed Stock Quote service example uses the namespace prefix n which is bound to the namespace name urn:xmethods-delayed-quotes through the xmlns:n="urn:xmethods-delayed-quotes binding. The use of namespace prefixes and namespace names is also required to enable SOAP applications to validate the content of SOAP messages. The namespace name in the service response is verified by the stub routine by using the information supplied in a namespace mapping table that is required to be part of gSOAP client and service application codes. The table is accessed at run time to resolve namespace bindings, both by the generated stub's data structure serializer for encoding the client request and by the generated stub's data structure deserializer to decode and validate the service response. The namespace mapping table should not be part of the header file input to the gSOAP stub and skeleton compiler. Service details including namespace bindings may be provided with gSOAP directives in a header file, see Section 18.2.
The namespace mapping table for the Delayed Stock Quote client is:

struct Namespace namespaces[] =
{   // {"ns-prefix", "ns-name"}
   {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"}, // MUST be first
   {"SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/"}, // MUST be second
   {"xsi", "http://www.w3.org/2001/XMLSchema-instance"}, // MUST be third
   {"xsd", "http://www.w3.org/2001/XMLSchema"}, // 2001 XML Schema
   {"ns1", "urn:xmethods-delayed-quotes"}, // given by the service description
   {NULL, NULL} // end of table
};

The first four namespace entries in the table consist of the standard namespaces used by the SOAP 1.1 protocol. In fact, the namespace mapping table is explicitly declared to enable a programmer to specify the SOAP encoding style and to allow the inclusion of namespace-prefix with namespace-name bindings to comply to the namespace requirements of a specific SOAP service. For example, the namespace prefix ns1, which is bound to urn:xmethods-delayed-quotes by the namespace mapping table shown above, is used by the generated stub routine to encode the getQuote request. This is performed automatically by the gSOAP compiler by using the ns1 prefix of the ns1__getQuote method name specified in the getQuote.h header file. In general, if a function name of a remote method, struct name, class name, enum name, or field name of a struct or class has a pair of underscores, the name has a namespace prefix that must be defined in the namespace mapping table.
The namespace mapping table will be output as part of the SOAP Envelope by the stub routine. For example:

...
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
   xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:ns1="urn:xmethods-delayed-quotes"
   SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
...

The namespace bindings will be used by a SOAP service to validate the SOAP request.

7.1.3  Example

The incorporation of namespace prefixes into C++ identifier names is necessary to distinguish remote methods that share the same name but are provided by separate Web services and/or organizations. Consider for example:

// Contents of file "getQuote.h":
int ns1__getQuote(char *symbol, float &Result);
int ns2__getQuote(char *ticker, char *&quote);

Recall that the namespace prefix is always separated from the name of a remote method by a pair of underscores (__).
This example enables a client program to connect to a (hypothetical) Stock Quote service with remote methods that can only be distinguished by their namespaces. Consequently, two different namespace prefixes had to be used as part of the remote method names.
The namespace prefix convention can also be applied to class declarations that contain SOAP compound values that share the same name but have different namespaces that refer to different XML Schemas. For example:

class e__Address // an electronic address
{
   char *email;
   char *url;
};
class s__Address // a street address
{
   char *street;
   int number;
   char *city;
};

The namespace prefix is separated from the name of a data type by a pair of underscores (__).
An instance of e__Address is encoded by the generated serializer for this type as an Address element with namespace prefix e:

<e:Address xsi:type="e:Address">
<email xsi:type="string">me@home</email>
<url xsi:type="string">www.me.com</url>
</e:Address>

While an instance of s__Address is encoded by the generated serializer for this type as an Address element with namespace prefix s:

<s:Address xsi:type="s:Address">
<street xsi:type="string">Technology Drive</street>
<number xsi:type="int">5</number>
<city xsi:type="string">Softcity</city>
</s:Address>

The namespace mapping table of the client program must have entries for e and s that refer to the XML Schemas of the data types:

struct Namespace namespaces[] =
{ ...
   {"e", "http://www.me.com/schemas/electronic-address"},
   {"s", "http://www.me.com/schemas/street-address"},
...

This table is required to be part of the client application to allow access by the serializers and deserializers of the data types at run time.

7.1.4  How to Generate C++ Client Proxy Classes

Proxy classes for C++ client applications are automatically generated by the gSOAP compiler.
There is a new and improved code generation capability for proxy classes, which is activated with the soapcpp2 -i option. These new proxy classes are derived from the soap structure, have a cleaner interface and offer more capabilites.
To illustrate the generation of a "standard" (old) proxy class, the getQuote.h header file example of the previous section is augmented with the appropriate directives to enable the gSOAP compiler to generate the proxy class. Similar directives are included in the header file by the WSDL importer.

// Content of file "getQuote.h":
//gsoap ns1 service name: Quote
//gsoap ns1 service location: http://services.xmethods.net/soap
//gsoap ns1 service namespace: urn:xmethods-delayed-quotes
//gsoap ns1 service style: rpc
//gsoap ns1 service encoding: encoded
//gsoap ns1 service method-action: getQuote ""
int ns1__getQuote(char *symbol, float &Result);

The first three directives provide the service name which is used to name the proxy class, the service location (endpoint), and the schema. The forth and fifth directives specify that SOAP RPC encoding is used, which is required by this service. The last directive defines the optional SOAPAction, which is a string associated with SOAP 1.1 operations. This directive must be provided for each remote method when the SOAPAction is required. Compilation of this header file with the gSOAP compiler soapcpp2 creates a new file soapQuoteProxy.h with the following contents:

#include "soapH.h"
class Quote
{ public:
   struct soap *soap;
   const char *endpoint;
   Quote() { soap = soap_new(); endpoint = "http://services.xmethods.net/soap"; };
   ~Quote() { if (soap) { soap_destroy(soap); soap_end(soap); soap_free(soap); }};
   int getQuote(char *symbol, float &Result) { return soap ? soap_call_ns1__getQuote(soap, endpoint, "", symbol, Result) : SOAP_EOM; };
};

The gSOAP environment and endpoint are declared public to enable access for run-time customization.
This generated proxy class can be included into a client application together with the generated namespace table as shown in this example:

#include "soapQuoteProxy.h" // get proxy
#include "Quote.nsmap" // get namespace bindings
int main()
{
   Quote q;
   float r;
   if (q.ns1__getQuote("IBM", r) == SOAP_OK)
      std::cout << r << std::endl;
   else
      soap_print_fault(q.soap, stderr);
   return 0;
}

The Quote constructor allocates and initializes a gSOAP environment for the instance. All the HTTP and SOAP/XML processing is hidden and performed on the background.
You can use soapcpp2 compiler option -n together with -p to create a local namespaces table to avoid link conflicts when you need multiple namespace tables or need to combine multiple clients, see also Sections 8.1 and 18.34, and you can use a C++ code namespace to create a namespace qualified proxy class, see Section 18.33.
Don't forget to try the soapcpp2 -i option to generate proxy classes derived from the base soap structure. In addition, these classes offer more functionality.

7.1.5  XSD Type Encoding Considerations

Many SOAP services require the explicit use of XML Schema types in the SOAP payload. The default encoding, which is also adopted by the gSOAP compiler, assumes SOAP RPC encoding which only requires the use of types to handle polymorphic cases. Nevertheless, the use of XSD typed messages is advised to improve interoperability. XSD types are introduced with typedef definitions in the header file input to the gSOAP compiler. The type name defined by a typedef definition corresponds to an XML Schema type (XSD type). For example, the following typedef declarations define various built-in XSD types implemented as primitive C/C++ types:

// Contents of header file:
...
typedef char *xsd__string; // encode xsd__string value as the xsd:string schema type
typedef char *xsd__anyURI; // encode xsd__anyURI value as the xsd:anyURI schema type
typedef float xsd__float; // encode xsd__float value as the xsd:float schema type
typedef long xsd__int; // encode xsd__int value as the xsd:int schema type
typedef bool xsd__boolean; // encode xsd__boolean value as the xsd:boolean schema type
typedef unsigned long long xsd__positiveInteger; // encode xsd__positiveInteger value as the xsd:positiveInteger schema type
...

This simple mechanism informs the gSOAP compiler to generate serializers and deserializers that explicitly encode and decode the primitive C++ types as built-in primitive XSD types when the typedefed type is used in the parameter signature of a remote method (or when used nested within structs, classes, and arrays). At the same time, the use of typedef does not force any recoding of a C++ client or Web service application as the internal C++ types used by the application are not required to be changed (but still have to be primitive C++ types, see Section 10.3.2 for alternative class implementations of primitive XSD types which allows for the marshalling of polymorphic primitive types).

7.1.6  Example

Reconsider the getQuote example, now rewritten with explicit XSD types to illustrate the effect:

// Contents of file "getQuote.h":
typedef char *xsd__string;
typedef float xsd__float;
int ns1__getQuote(xsd__string symbol, xsd__float &Result);

This header file is compiled by the gSOAP stub and skeleton compiler and the compiler generates source code for the function soap_call_ns1__getQuote, which is identical to the "old" proxy:

int soap_call_ns1__getQuote(struct soap *soap, char *URL, char *action, char *symbol, float &Result);

The client application does not need to be rewritten and can still call the proxy using the "old" parameter signature. In contrast to the previous implementation of the stub however, the encoding and decoding of the data types by the stub has been changed to explicitly use the XSD types in the message payload.
For example, when the client application calls the proxy, the proxy produces a SOAP request with an xsd:string:

...
<SOAP-ENV:Body>
<ns1:getQuote><symbol xsi:type="xsd:string">IBM</symbol>
</ns1:getQuote>
</SOAP-ENV:Body>
...

The service response is:

...
<soap:Body>
<n:getQuoteResponse xmlns:n="urn:xmethods-delayed-quotes»
<Result xsi:type="xsd:float»41.81</Result>
</n:getQuoteResponse>
</soap:Body>
...

The validation of this service response by the stub routine takes place by matching the namespace names (URIs) that are bound to the xsd namespace prefix. The stub also expects the getQuoteResponse element to be associated with URI urn:xmethods-delayed-quotes through the binding of the namespace prefix ns1 in the namespace mapping table. The service response uses namespace prefix n for the getQuoteResponse element. This namespace prefix is bound to the same URI urn:xmethods-delayed-quotes and therefore the service response is assumed to be valid. The response is rejected and a SOAP fault is generated when the URIs do not match.

7.1.7  How to Change the Response Element Name

There is no standardized convention for the response element name in a SOAP response message, although it is recommended that the response element name is the method name ending with "Response". For example, the response element of getQuote is getQuoteResponse.
The response element name can be specified explicitly using a struct or class declaration in the header file. The struct or class name represents the SOAP response element name used by the service. Consequently, the output parameter of the remote method must be declared as a field of the struct or class. The use of a struct or a class for the service response is fully SOAP 1.1 compliant. In fact, the absence of a struct or class indicates to the gSOAP compiler to automatically generate a struct for the response which is internally used by a stub.

7.1.8  Example

Reconsider the getQuote remote method specification which can be rewritten with an explicit declaration of a SOAP response element as follows:

// Contents of "getQuote.h":
typedef char *xsd__string;
typedef float xsd__float;
struct ns1__getQuoteResponse {xsd__float Result;};
int ns1__getQuote(xsd__string symbol, struct ns1__getQuoteResponse &r);

The SOAP request is the same as before:

...
<SOAP-ENV:Body>
<ns1:getQuote><symbol xsi:type="xsd:string">IBM</symbol>
</ns1:getQuote>
</SOAP-ENV:Body>
...

The difference is that the service response is required to match the specified getQuoteResponse name and its namespace URI:

...
<soap:Body>
<n:getQuoteResponse xmlns:n='urn:xmethods-delayed-quotes'>
<Result xsi:type='xsd:float'>41.81</Result>
</n:getQuoteResponse>
</soap:Body>
...

This use of a struct or class enables the adaptation of the default SOAP response element name and/or namespace URI when required.
Note that the struct (or class) declaration may appear within the function prototype declaration. For example:

// Contents of "getQuote.h":
typedef char *xsd__string;
typedef float xsd__float;
int ns1__getQuote(xsd__string symbol, struct ns1__getQuoteResponse {xsd__float Result;} &r);

This example combines the declaration of the response element of the remote method with the function prototype of the remote method.

7.1.9  How to Specify Multiple Output Parameters

The gSOAP stub and skeleton compiler uses the convention that the last parameter of the function prototype declaration of a remove method in a header file is also the only single output parameter of the method. All other parameters are considered input parameters of the remote method. To specify a remote method with multiple output parameters, a struct or class must be declared for the remote method response, see also 7.1.7. The fields of the struct or class are the output parameters of the remote method. Both the order of the input parameters in the function prototype and the order of the output parameters (the fields in the struct or class) is not significant. However, the SOAP 1.1 specification states that input and output parameters may be treated as having anonymous parameter names which requires a particular ordering, see Section 7.1.13.

7.1.10  Example

As an example, consider a hypothetical remote method getNames with a single input parameter SSN and two output parameters first and last. This can be specified as:

// Contents of file "getNames.h":
int ns3__getNames(char *SSN, struct ns3__getNamesResponse {char *first; char *last;} &r);

The gSOAP stub and skeleton compiler takes this header file as input and generates source code for the function soap_call_ns3__getNames. When invoked by a client application, the proxy produces the SOAP request:

...
<SOAP-ENV:Envelope ... xmlns:ns3="urn:names" ...>
...
<ns3:getNames>
<SSN>999 99 9999</SSN>
</ns3:getNames>
...

The response by a SOAP service could be:

...
<m:getNamesResponse xmlns:m="urn:names">
<first>John</first>
<last>Doe</last>
</m:getNamesResponse>
...

where first and last are the output parameters of the getNames remote method of the service.
As another example, consider a remote method copy with an input parameter and an output parameter with identical parameter names (this is not prohibited by the SOAP 1.1 protocol). This can be specified as well using a response struct:

// Content of file "copy.h":
int X_rox__copy_name(char *name, struct X_rox__copy_nameResponse {char *name;} &r);

The use of a struct or class for the remote method response enables the declaration of remote methods that have parameters that are passed both as input and output parameters.
The gSOAP compiler takes the copy.h header file as input and generates the soap_call_X_rox__copy_name proxy. When invoked by a client application, the proxy produces the SOAP request:

...
<SOAP-ENV:Envelope ... xmlns:X-rox="urn:copy" ...>
...
<X-rox:copy-name>
<name>SOAP</name>
</X-rox:copy-name>
...

The response by a SOAP copy service could be something like:

...
<m:copy-nameResponse xmlns:m="urn:copy">
<name>SOAP</name>
</m:copy-nameResponse>
...

The name will be parsed and decoded by the proxy and returned in the name field of the struct X_rox__copy_nameResponse &r parameter.

7.1.11  How to Specify Output Parameters With struct/class Compound Data Types

If the single output parameter of a remote method is a complex data type such as a struct or class it is necessary to specify the response element of the remote method as a struct or class at all times. Otherwise, the output parameter will be considered the response element (!), because of the response element specification convention used by gSOAP, as discussed in 7.1.7.

7.1.12  Example

This is is best illustrated with an example. The Flighttracker service by ObjectSpace provides real time flight information for flights in the air. It requires an airline code and flight number as parameters. The remote method name is getFlightInfo and the method has two string parameters: the airline code and flight number, both of which must be encoded as xsd:string types. The method returns a getFlightResponse response element with a return output parameter that is of complex type FlightInfo. The type FlightInfo is represented by a class in the header file, whose field names correspond to the FlightInfo accessors:

// Contents of file "flight.h":
typedef char *xsd__string;
class ns2__FlightInfo
{
   public:
   xsd__string airline;
   xsd__string flightNumber;
   xsd__string altitude;
   xsd__string currentLocation;
   xsd__string equipment;
   xsd__string speed;
};
struct ns1__getFlightInfoResponse {ns2__FlightInfo _return;};
int ns1__getFlightInfo(xsd__string param1, xsd__string param2, struct ns1__getFlightInfoResponse &r);

The response element ns1__getFlightInfoResponse is explicitly declared and it has one field: return_ of type ns2__FlightInfo. Note that return_ has a trailing underscore to avoid a name clash with the return keyword, see Section 9.3 for details on the translation of C++ identifiers to XML element names.
The gSOAP compiler generates the soap_call_ns1__getFlightInfo proxy. Here is an example fragment of a client application that uses this proxy to request flight information:

struct soap soap;
...
soap_init(&soap);
...
soap_call_ns1__getFlightInfo(&soap, "testvger.objectspace.com/soap/servlet/rpcrouter",
   "urn:galdemo:flighttracker", "UAL", "184", r);
...
struct Namespace namespaces[] =
{
   {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"},
   {"SOAP-ENC","http://schemas.xmlsoap.org/soap/encoding/"},
   {"xsi", "http://www.w3.org/2001/XMLSchema-instance"},
   {"xsd", "http://www.w3.org/2001/XMLSchema"},
   {"ns1", "urn:galdemo:flighttracker"},
   {"ns2", "http://galdemo.flighttracker.com"},
   {NULL, NULL}
};

When invoked by a client application, the proxy produces the SOAP request:

POST /soap/servlet/rpcrouter HTTP/1.1
Host: testvger.objectspace.com
Content-Type: text/xml
Content-Length: 634
SOAPAction: "urn:galdemo:flighttracker"

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
   xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:ns1="urn:galdemo:flighttracker"
   xmlns:ns2="http://galdemo.flighttracker.com"
   SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:getFlightInfo xsi:type="ns1:getFlightInfo">
<param1 xsi:type="xsd:string">UAL</param1>
<param2 xsi:type="xsd:string">184</param2>
</ns1:getFlightInfo>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

The Flighttracker service responds with:

HTTP/1.1 200 ok
Date: Thu, 30 Aug 2001 00:34:17 GMT
Server: IBM_HTTP_Server/1.3.12.3 Apache/1.3.12 (Win32)
Set-Cookie: sesessionid=2GFVTOGC30D0LGRGU2L4HFA;Path=/
Cache-Control: no-cache="set-cookie,set-cookie2"
Expires: Thu, 01 Dec 1994 16:00:00 GMT
Content-Length: 861
Content-Type: text/xml; charset=utf-8
Content-Language: en

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SOAP-ENV:Body>
<ns1:getFlightInfoResponse xmlns:ns1="urn:galdemo:flighttracker"
   SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<return xmlns:ns2="http://galdemo.flighttracker.com" xsi:type="ns2:FlightInfo">
<equipment xsi:type="xsd:string">A320</equipment>
<airline xsi:type="xsd:string">UAL</airline>
<currentLocation xsi:type="xsd:string">188 mi W of Lincoln, NE</currentLocation>
<altitude xsi:type="xsd:string">37000</altitude>
<speed xsi:type="xsd:string">497</speed>
<flightNumber xsi:type="xsd:string">184</flightNumber>
</return>
</ns1:getFlightInfoResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

The proxy returns the service response in variable r of type struct ns1__getFlightInfoResponse and this information can be displayed by the client application with the following code fragment:

cout << r.return_.equipment << " flight " << r.return_.airline << r.return_.flightNumber
    << " traveling " << r.return_.speed << " mph " << " at " << r.return_.altitude
    << " ft, is located " << r.return_.currentLocation << endl;

This code displays the service response as:

A320 flight UAL184 traveling 497 mph at 37000 ft, is located 188 mi W of Lincoln, NE

Note: the flight tracker service is no longer available since 9/11/2001. It is kept in the documentation as an example to illustrate the use of structs/classes and response types.

7.1.13  How to Specify Anonymous Parameter Names

The SOAP 1.1 protocol allows parameter names to be anonymous. That is, the name(s) of the output parameters of a remote method are not strictly required to match a client's view of the parameters names. Also, the input parameter names of a remote method are not strictly required to match a service's view of the parameter names. Although this convention is likely to be deprecated in SOAP 1.2, the gSOAP compiler can generate stub and skeleton routines that support anonymous parameters. Parameter names are implicitly anonymous by omitting the parameter names in the function prototype of the remote method. For example:

// Contents of "getQuote.h":
typedef char *xsd__string;
typedef float xsd__float;
int ns1__getQuote(xsd__string, xsd__float&);

To make parameter names explicitly anonymous on the receiving side (client or service), the parameter names should start with an underscore (_) in the function prototype in the header file.
For example:

// Contents of "getQuote.h":
typedef char *xsd__string;
typedef float xsd__float;
int ns1__getQuote(xsd__string symbol, xsd__float &_return);

Or, alternatively with a response struct:

// Contents of "getQuote.h":
typedef char *xsd__string;
typedef float xsd__float;
struct ns1__getQuoteResponse {xsd__float _return;};
int ns1__getQuote(xsd__string symbol, struct ns1__getQuoteResponse &r);

In this example, _return is an anonymous output parameter. As a consequence, the service response to a request made by a client created with gSOAP using this header file specification may include any name for the output parameter in the SOAP payload. The input parameters may also be anonymous. This affects the implementation of Web services in gSOAP and the matching of parameter names by the service.
Caution: when anonymous parameter names are used, the order of the parameters in the function prototype of a remote method is significant.

7.1.14  How to Specify a Method with No Input Parameters

To specify a remote method that has no input parameters, just provide a function prototype with one parameter which is the output parameter (some C/C++ compilers will not compile and complain about an empty struct: use compile flag -DWITH_NOEMPTYSTRUCT to compile the generated code for these cases). This struct is generated by gSOAP to contain the SOAP request message. To fix this, provide one input parameter of type void* (gSOAP can not serialize void* data). For example:

struct ns3__SOAPService
{
   public:
   int ID;
   char *name;
   char *owner;
   char *description;
   char *homepageURL;
   char *endpoint;
   char *SOAPAction;
   char *methodNamespaceURI;
   char *serviceStatus;
   char *methodName;
   char *dateCreated;
   char *downloadURL;
   char *wsdlURL;
   char *instructions;
   char *contactEmail;
   char *serverImplementation;
};
struct ArrayOfSOAPService {struct ns3__SOAPService *__ptr; int __size;};
int ns__getAllSOAPServices(void *_, struct ArrayOfSOAPService &_return);

The ns__getAllSOAPServices method has one void* input parameter which is ignored by the serializer to produce the request message.
Most C/C++ compilers allow empty structs and therefore the void* parameter is not required.

7.1.15  How to Specify a Method with No Output Parameters

To specify a remote method that has no output parameters, just provide a function prototype with a response struct that is empty. For example:

enum ns__event { off, on, stand_by };
int ns__signal(enum ns__event in, struct ns__signalResponse { } *out);

Since the response struct is empty, no output parameters are specified. Most C/C++ compilers allow empty structs. For those that don't, use a void* parameter in the struct. This parameter is not (de)serialized.
Some SOAP resources refer to SOAP RPC with empty responses as one way SOAP messaging. However, we refer to one-way massaging by asynchronous explicit send and receive operations as described in Section 7.3. The latter view of one-way SOAP messaging is also in line with Basic Profile 1.0.

7.2  How to Use the gSOAP Stub and Skeleton Compiler to Build SOAP Web Services

The gSOAP stub and skeleton compiler generates skeleton routines in C++ source form for each of the remote methods specified as function prototypes in the header file processed by the gSOAP compiler. The skeleton routines can be readily used to implement the remote methods in a new SOAP Web service. The compound data types used by the input and output parameters of SOAP remote methods must be declared in the header file, such as structs, classes, arrays, and pointer-based data structures (graphs) that are used as the data types of the parameters of a remote method. The gSOAP compiler automatically generates serializers and deserializers for the data types to enable the generated skeleton routines to encode and decode the contents of the parameters of the remote methods. The gSOAP compiler also generates a remote method request dispatcher routine that will serve requests by calling the appropriate skeleton when the SOAP service application is installed as a CGI application on a Web server.

7.2.1  Example

The following example specifies three remote methods to be implemented by a new SOAP Web service:

// Contents of file "calc.h":
typedef double xsd__double;
int ns__add(xsd__double a, xsd__double b, xsd__double &result);
int ns__sub(xsd__double a, xsd__double b, xsd__double &result);
int ns__sqrt(xsd__double a, xsd__double &result);

The add and sub methods are intended to add and subtract two double floating point numbers stored in input parameters a and b and should return the result of the operation in the result output parameter. The qsrt method is intended to take the square root of input parameter a and to return the result in the output parameter result. The xsd__double type is recognized by the gSOAP compiler as the xsd:double XSD Schema data type. The use of typedef is a convenient way to associate primitive C types with primitive XML Schema data types.
To generate the skeleton routines, the gSOAP compiler is invoked from the command line with:

soapcpp2 calc.h

The compiler generates the skeleton routines for the add, sub, and sqrt remote methods specified in the calc.h header file. The skeleton routines are respectively, soap_serve_ns__add, soap_serve_ns__sub, and soap_serve_ns__sqrt and saved in the file soapServer.cpp. The generated file soapC.cpp contains serializers and deserializers for the skeleton. The compiler also generates a service dispatcher: the soap_serve function handles client requests on the standard input stream and dispatches the remote method requests to the appropriate skeletons to serve the requests. The skeleton in turn calls the remote method implementation function. The function prototype of the remote method implementation function is specified in the header file that is input to the gSOAP compiler.
Here is an example Calculator service application that uses the generated soap_serve routine to handle client requests:

// Contents of file "calc.cpp":
#include "soapH.h"
#include < math.h > // for sqrt()
main()
{
   soap_serve(soap_new()); // use the remote method request dispatcher
}
// Implementation of the "add" remote method:
int ns__add(struct soap *soap, double a, double b, double &result)
{
   result = a + b;
   return SOAP_OK;
}
// Implementation of the "sub" remote method:
int ns__sub(struct soap *soap, double a, double b, double &result)
{
   result = a - b;
   return SOAP_OK;
}
// Implementation of the "sqrt" remote method:
int ns__sqrt(struct soap *soap, double a, double &result)
{
   if (a > = 0)
   {
      result = sqrt(a);
      return SOAP_OK;
   }
   else
      return soap_receiver_fault(soap, "Square root of negative number", "I can only take the square root of a non-negative number");
}
// As always, a namespace mapping table is needed:
struct Namespace namespaces[] =
{   // {"ns-prefix", "ns-name"}
   {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"},
   {"SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/"},
   {"xsi", "http://www.w3.org/2001/XMLSchema-instance"},
   {"xsd", "http://www.w3.org/2001/XMLSchema"},
   {"ns", "urn:simple-calc"}, // bind "ns" namespace prefix
   {NULL, NULL}
};

Note that the remote methods have an extra input parameter which is a pointer to the gSOAP runtime environment. The implementation of the remote methods MUST return a SOAP error code. The code SOAP_OK denotes success, while SOAP_FAULT denotes an exception with details that can be defined by the user. The exception description can be assigned to the soap->fault->faultstring string and details can be assigned to the soap->fault->detail string. This is SOAP 1.1 specific. SOAP 1.2 requires the soap->fault->SOAP_ENV__Reason and the soap->fault->SOAP_ENV__Detail strings to be assigned. Better is to use the soap_receiver_fault function that allocates a fault struct and sets the SOAP Fault string and details regardless of the SOAP 1.1 or SOAP 1.2 version used. The soap_receiver_fault function returns SOAP_FAULT, i.e. an application-specific fault. The fault exception will be passed on to the client of this service.
This service application can be readily installed as a CGI application. The service description would be:

Endpoint URL: the URL of the CGI application
SOAP action: "" (2 quotes)
Remote method namespace: urn:simple-calc
Remote method name: add
   Input parameters: a of type xsd:double and b of type xsd:double
   Output parameter: result of type xsd:double
Remote method name: sub
   Input parameters: a of type xsd:double and b of type xsd:double
   Output parameter: result of type xsd:double
Remote method name: sqrt
   Input parameter: a of type xsd:double
   Output parameter: result of type xsd:double or a SOAP Fault

The soapcpp2 compile generates a WSDL file for this service, see Section 7.2.8.
Unless the CGI application inspects and checks the environment variable SOAPAction which contains the SOAP action request by a client, the SOAP action is ignored by the CGI application. SOAP actions are specific to the SOAP protocol and provide a means for routing requests and for security reasons (e.g. firewall software can inspect SOAP action headers to grant or deny the SOAP request. Note that this requires the SOAP service to check the SOAP action header as well to match it with the remote method.)
The header file input to the gSOAP compiler does not need to be modified to generate client stubs for accessing this service. Client applications can be developed by using the same header file as for which the service application was developed. For example, the soap_call_ns__add stub routine is available from the soapClient.cpp file after invoking the gSOAP compiler on the calc.h header file. As a result, client and service applications can be developed without the need to know the details of the SOAP encoding used.

7.2.2  MSVC++ Builds

7.2.3  How to Create a Stand-Alone gSOAP Service

The deployment of a Web service as a CGI application is an easy means to provide your service on the Internet. gSOAP services can also run as stand-alone services on any port by utilizing the built-in HTTP and TCP/IP stacks. The stand-alone services can be run on port 80 thereby providing Web server capabilities restricted to SOAP RPC.
To create a stand-alone service, only the main routine of the service needs to be modified as follows. Instead of just calling the soap_serve routine, the main routine is changed into:

int main()
{
   struct soap soap;
   int m, s; // master and slave sockets
   soap_init(&soap);
   m = soap_bind(&soap, "machine.cs.fsu.edu", 18083, 100);
   if (m < 0)
      soap_print_fault(&soap, stderr);
   else
   {
      fprintf(stderr, "Socket connection successful: master socket = %d\n", m);
      for (int i = 1; ; i++)
      {
         s = soap_accept(&soap);
         if (s < 0)
         {
            soap_print_fault(&soap, stderr);
            break;
         }
         fprintf(stderr, "%d: accepted connection from IP=%d.%d.%d.%d socket=%d", i,
            (soap.ip >> 24)&0xFF, (soap.ip >> 16)&0xFF, (soap.ip >> 8)&0xFF, soap.ip&0xFF, s);
         if (soap_serve(&soap) != SOAP_OK) // process RPC request
            soap_print_fault(&soap, stderr); // print error
         fprintf(stderr, "request served\n");
         soap_destroy(&soap); // clean up class instances
         soap_end(&soap); // clean up everything and close socket
      }
   }
   soap_done(&soap); // close master socket and detach environment
}

The soap_serve dispatcher handles one request or multiple requests when HTTP keep-alive is enabled (with the SOAP_IO_KEEPALIVE flag see Section 18.11).
The gSOAP functions that can be used are:

Function Description
soap_new() Allocates and Initializes gSOAP context
soap_init(struct soap *soap) Initializes a stack-allocated gSOAP context (required once)
soap_bind(struct soap *soap, char *host, int port, int backlog) Returns master socket (backlog = max. queue size for requests). When host==NULL: host is the machine on which the service runs
soap_accept(struct soap *soap) Returns slave socket
soap_end(struct soap *soap) Clean up deserialized data (except class instances) and temporary data
soap_free_temp(struct soap *soap) Clean up temporary data only
soap_destroy(struct soap *soap) Clean up deserialized class instances (note: this function will be renamed with option -n
soap_done(struct soap *soap) Reset and detach context: close master/slave sockets and remove callbacks
soap_free(struct soap *soap) Detach and deallocate context (soap_new())

The host name in soap_bind may be NULL to indicate that the current host should be used.
The soap.accept_timeout attribute of the gSOAP run-time environment specifies the timeout value for a non-blocking soap_accept(&soap) call. See Section 18.17 for more details on timeout management.
See Section 8.13 for more details on memory management.
A client application connects to this stand-alone service with the endpoint machine.cs.fsu.edu:18083. A client may use the http:// prefix. When absent, no HTTP header is send and no HTTP-based information will be communicated to the service.

7.2.4  How to Create a Multi-Threaded Stand-Alone Service

Multi-threading a Web Service is essential when the response times for handling requests by the service are (potentially) long or when keep-alive is enabled, see Section 18.11. In case of long response times, the latencies introduced by the unrelated requests may become prohibitive for a successful deployment of a stand-alone service. When HTTP keep-alive is enabled, a client may not close the socket on time, thereby preventing other clients from connecting.
gSOAP 2.0 and higher is thread safe and supports the implementation of multi-threaded stand-alone services in which a thread is used to handle a request.
The following example illustrates the use of threads to improve the quality of service by handling new requests in separate threads:

#include "soapH.h"
#include < pthread.h >
#define BACKLOG (100) // Max. request backlog
int main(int argc, char **argv)
{
   struct soap soap;
   soap_init(&soap);
   if (argc < 2) // no args: assume this is a CGI application
   {
      soap_serve(&soap); // serve request, one thread, CGI style
      soap_destroy(&soap); // dealloc C++ data
      soap_end(&soap); // dealloc data and clean up
   }
   else 
   {
      soap.send_timeout = 60; // 60 seconds
      soap.recv_timeout = 60; // 60 seconds
      soap.accept_timeout = 3600; // server stops after 1 hour of inactivity
      soap.max_keep_alive = 100; // max keep-alive sequence
      void *process_request(void*);
      struct soap *tsoap;
      pthread_t tid;
      int port = atoi(argv[1]); // first command-line arg is port
      SOAP_SOCKET m, s;
      m = soap_bind(&soap, NULL, port, BACKLOG);
      if (!soap_valid_socket(m))
         exit(1);
      fprintf(stderr, "Socket connection successful %d\n", m);
      for (;;)
      {
         s = soap_accept(&soap);
         if (!soap_valid_socket(s))
         {
            if (soap.errnum)
            {
               soap_print_fault(&soap, stderr);
               exit(1);
            }
            fprintf(stderr, "server timed out\n");
            break;
         }
         fprintf(stderr, "Thread %d accepts socket %d connection from IP %d.%d.%d.%d\n", i, s, (soap.ip >> 24)&0xFF, (soap.ip >> 16)&0xFF, (soap.ip >> 8)&0xFF, soap.ip&0xFF);
         tsoap = soap_copy(&soap); // make a safe copy
         if (!tsoap)
            break;
         pthread_create(&tid, NULL, (void*(*)(void*))process_request, (void*)tsoap);
      }
   }
   soap_done(&soap); // detach soap struct
   return 0;
}
void *process_request(void *soap)
{
   pthread_detach(pthread_self());
   soap_serve((struct soap*)soap);
   soap_destroy((struct soap*)soap); // dealloc C++ data
   soap_end((struct soap*)soap); // dealloc data and clean up
   soap_done((struct soap*)soap); // detach soap struct
   free(soap);
   return NULL;
}

Note: the code does not wait for threads to join the main thread upon program termination.
The soap_serve dispatcher handles one request or multiple requests when HTTP keep-alive is set with SOAP_IO_KEEPALIVE. The soap.max_keep_alive value can be set to the maximum keep-alive calls allowed, which is important to avoid a client from holding a thread indefinitely. The send and receive timeouts are set to avoid (intentionally) slow clients from holding a socket connection too long. The accept timeout is used to let the server terminate automatically after a period of inactivity.
The following example uses a pool of servers to limit the machine's resource utilization:

#include "soapH.h"
#include < pthread.h >
#define BACKLOG (100) // Max. request backlog
#define MAX_THR (10) // Max. threads to serve requests
int main(int argc, char **argv)
{
   struct soap soap;
   soap_init(&soap);
   if (argc < 2) // no args: assume this is a CGI application
   {
      soap_serve(&soap); // serve request, one thread, CGI style
      soap_destroy(&soap); // dealloc C++ data
      soap_end(&soap); // dealloc data and clean up
   }
   else 
   {
      struct soap *soap_thr[MAX_THR]; // each thread needs a runtime environment
      pthread_t tid[MAX_THR];
      int port = atoi(argv[1]); // first command-line arg is port
      SOAP_SOCKET m, s;
      int i;
      m = soap_bind(&soap, NULL, port, BACKLOG);
      if (!soap_valid_socket(m))
         exit(1);
      fprintf(stderr, "Socket connection successful %d\n", m);
      for (i = 0; i < MAX_THR; i++)
         soap_thr[i] = NULL;
      for (;;)
      {
         for (i = 0; i < MAX_THR; i++)
         {
            s = soap_accept(&soap);
            if (!soap_valid_socket(s))
            {
               if (soap.errnum)
               {
                  soap_print_fault(&soap, stderr);
                  continue; // retry
               }
               else
               {
                  fprintf(stderr, "Server timed out\n");
                  break;
               }
            }
            fprintf(stderr, "Thread %d accepts socket %d connection from IP %d.%d.%d.%d\n", i, s, (soap.ip >> 24)&0xFF, (soap.ip >> 16)&0xFF, (soap.ip >> 8)&0xFF, soap.ip&0xFF);
            if (!soap_thr[i]) // first time around
            {
               soap_thr[i] = soap_copy(&soap);
               if (!soap_thr[i])
               exit(1); // could not allocate
            }
            else// recycle soap environment
            {
               pthread_join(tid[i], NULL);
               fprintf(stderr, "Thread %d completed\n", i);
               soap_destroy(soap_thr[i]); // deallocate C++ data of old thread
               soap_end(soap_thr[i]); // deallocate data of old thread
            }
            soap_thr[i]->socket = s; // new socket fd
            pthread_create(&tid[i], NULL, (void*(*)(void*))soap_serve, (void*)soap_thr[i]);
         }
      }
      for (i = 0; i < MAX_THR; i++)
         if (soap_thr[i])
         {
            soap_done(soap_thr[i]); // detach context
            free(soap_thr[i]); // free up
         }
   }
   return 0;
}

The following functions can be used to setup a gSOAP runtime environment (struct soap):

Function Description
soap_init(struct soap *soap) Initializes a runtime environment (required only once)
struct soap *soap_new() Allocates, initializes, and returns a pointer to a runtime environment
struct soap *soap_copy(struct soap *soap) Allocates a new runtime environment and copies contents of the argument environment such that the new environment does not share data with the argument environment
soap_done(struct soap *soap) Reset, close communications, and remove callbacks

A new environment is initiated for each thread to guarantee exclusive access to runtime environments.
For clean termination of the server, the master socket can be closed and callbacks removed with soap_done(struct soap *soap).
The advantage of the code shown above is that the machine cannot be overloaded with requests, since the number of active services is limited. However, threads are still started and terminated. This overhead can be eliminated using a queue of requests (open sockets) as is shown in the code below.


#include "soapH.h"
#include < pthread.h >
#define BACKLOG (100) // Max. request backlog
#define MAX_THR (10) // Size of thread pool
#define MAX_QUEUE (1000) // Max. size of request queue
SOAP_SOCKET queue[MAX_QUEUE]; // The global request queue of sockets
int head = 0, tail = 0; // Queue head and tail
void *process_queue(void*);
int enqueue(SOAP_SOCKET);
SOAP_SOCKET dequeue();
pthread_mutex_t queue_cs;
pthread_cond_t queue_cv;
int main(int argc, char **argv)
{
   struct soap soap;
   soap_init(&soap);
   if (argc < 2) // no args: assume this is a CGI application
   {
      soap_serve(&soap); // serve request, one thread, CGI style
      soap_destroy(&soap); // dealloc C++ data
      soap_end(&soap); // dealloc data and clean up
   }
   else
   {
      struct soap *soap_thr[MAX_THR]; // each thread needs a runtime environment
      pthread_t tid[MAX_THR];
      int port = atoi(argv[1]); // first command-line arg is port
      SOAP_SOCKET m, s;
      int i;
      m = soap_bind(&soap, NULL, port, BACKLOG);
      if (!soap_valid_socket(m))
         exit(1);
      fprintf(stderr, "Socket connection successful %d\n", m);
      pthread_mutex_init(&queue_cs, NULL);
      pthread_cond_init(&queue_cv, NULL);
      for (i = 0; i < MAX_THR; i++)
      {
         soap_thr[i] = soap_copy(&soap);
         fprintf(stderr, "Starting thread %d\n", i);
         pthread_create(&tid[i], NULL, (void*(*)(void*))process_queue, (void*)soap_thr[i]);
      }
      for (;;)
      {
         s = soap_accept(&soap);
         if (!soap_valid_socket(s))
         {
            if (soap.errnum)
            {
               soap_print_fault(&soap, stderr);
               continue; // retry
            }
            else
            {
               fprintf(stderr, "Server timed out\n");
               break;
            }
         }
         fprintf(stderr, "Thread %d accepts socket %d connection from IP %d.%d.%d.%d\n", i, s, (soap.ip >> 24)&0xFF, (soap.ip >> 16)&0xFF, (soap.ip >> 8)&0xFF, soap.ip&0xFF);
         while (enqueue(s) == SOAP_EOM)
            sleep(1);
      }
      for (i = 0; i < MAX_THR; i++)
      {
         while (enqueue(SOAP_INVALID_SOCKET) == SOAP_EOM)
            sleep(1);
      }
      for (i = 0; i < MAX_THR; i++)
      {
         fprintf(stderr, "Waiting for thread %d to terminate... ", i);
         pthread_join(tid[i], NULL);
         fprintf(stderr, "terminated\n");
         soap_done(soap_thr[i]);
         free(soap_thr[i]);
      }
      pthread_mutex_destroy(&queue_cs);
      pthread_cond_destroy(&queue_cv);
   }
   soap_done(&soap);
   return 0;
}
void *process_queue(void *soap)
{
   struct soap *tsoap = (struct soap*)soap;
   for (;;)
   {
      tsoap->socket = dequeue();
      if (!soap_valid_socket(tsoap->socket))
         break;
      soap_serve(tsoap);
      soap_destroy(tsoap);
      soap_end(tsoap);
      fprintf(stderr, "served\n");
   }
   return NULL;
}
int enqueue(SOAP_SOCKET sock)
{
   int status = SOAP_OK;
   int next;
   pthread_mutex_lock(&queue_cs);
   next = tail + 1;
   if (next > = MAX_QUEUE)
      next = 0;
   if (next == head)
      status = SOAP_EOM;
   else
   {
      queue[tail] = sock;
      tail = next;
   }
   pthread_cond_signal(&queue_cv);
   pthread_mutex_unlock(&queue_cs);
   return status;
}
SOAP_SOCKET dequeue()
{
   SOAP_SOCKET sock;
   pthread_mutex_lock(&queue_cs);
   while (head == tail)       pthread_cond_wait(&queue_cv, &queue_cs);
   sock = queue[head++];
   if (head > = MAX_QUEUE)
      head = 0;
   pthread_mutex_unlock(&queue_cs);
   return sock;
}

Note: the plugin/threads.h and plugin/threads.c code can be used for a portable implementation. Instead of POSIX calls, use MUTEX_LOCK, MUTEX_UNLOCK, and COND_WAIT. These are wrappers for Win API calls or POSIX calls.

7.2.5  How to Pass Application Data to Service Methods

The void *soap.user field can be used to pass application data to service methods. This field should be set before the soap_serve() call. The service method can access this field to use the application-dependent data. The following example shows how a non-static database handle is initialized and passed to the service methods:

{ ...
   struct soap soap;
   database_handle_type database_handle;
   soap_init(&soap);    soap.user = (void*)database_handle;
   ...
   soap_serve(&soap); // call the remove method dispatcher to handle request
   ...
}
int ns__myMethod(struct soap *soap, ...)
{ ...
   fetch((database_handle_type*)soap->user);
// get data    ...
   return SOAP_OK;
}

Another way to pass application data around in a more organized way is accomplished with plugins, see Section 18.36.

7.2.6  Some Web Service Implementation Issues

The same client header file specification issues apply to the specification and implementation of a SOAP Web service. Refer to

7.2.7  How to Generate C++ Server Object Classes

Server object classes for C++ server applications are automatically generated by the gSOAP compiler.
There are two modes for generating classes. Use soapcpp2 option -i to generate improved class definitions where the class' member functions are the service methods. The older examples use a C-like approach with globally defined service methods, which is illustated here with a calculator example:

// Content of file "calc.h":
//gsoap ns service name: Calculator
//gsoap ns service style: rpc
//gsoap ns service encoding: encoded
//gsoap ns service location: http://www.cs.fsu.edu/~engelen/calc.cgi
//gsoap ns schema namespace: urn:calc
//gsoap ns service method-action: add ""
int ns__add(double a, double b, double &result); int ns__sub(double a, double b, double &result); int ns__mul(double a, double b, double &result); int ns__div(double a, double b, double &result);

The first three directives provide the service name which is used to name the service class, the service location (endpoint), and the schema. The fourth directive defines the optional SOAPAction for the method, which is a string associated with SOAP 1.1 operations. Compilation of this header file with the gSOAP compiler soapcpp2 creates a new file soapCalculatorObject.h with the following contents:

#include "soapH.h"
class CalculatorObject : public soap
{ public:
   Calculator() { ... };
   ~Calculator() { ... }};
   int serve() { return soap_serve(this); };
};

This generated server object class can be included into a server application together with the generated namespace table as shown in this example:

#include "soapCalculatorObject.h" // get server object
#include "Calculator.nsmap" // get namespace bindings
int main()
{
   CalculatorObject c;
   return c.serve(); // calls soap_serve to serve as CGI application (using stdin/out)
}
int ns__add(double a, double b, double &result)
{
   result = a + b;
   return SOAP_OK;
}
... sub(), mul(), and div() implementations ...

You can use soapcpp2 compiler option -n together with -p to create a local namespaces table to avoid link conflict when you need to combine multiple tables and/or multiple servers, see also Sections 8.1 and 18.34, and you can use a C++ code namespace to create a namespace qualified server object class, see Section 18.33.
The example above serves requests over stdin/out. Use the bind and accept calls to create a stand-alone server to service inbound requests over sockets, see also 7.2.3.

7.2.8  How to Generate WSDL Service Descriptions

The gSOAP stub and skeleton compiler soapcpp2 generates WSDL (Web Service Description Language) service descriptions and XML Schema files when processing a header file. The compiler produces one WSDL file for a set of remote methods. The names of the function prototypes of the remote methods must use the same namespace prefix and the namespace prefix is used to name the WSDL file. If multiple namespace prefixes are used to define remote methods, multiple WSDL files will be created and each file describes the set of remote methods belonging to a namespace prefix.
In addition to the generation of the ns.wsdl file, a file with a namespace mapping table is generated by the gSOAP compiler. An example mapping table is shown below:

struct Namespace namespaces[] =
{
   {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"},
   {"SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/"},
   {"xsi", "http://www.w3.org/2001/XMLSchema-instance", \"http://www.w3.org/*/XMLSchema-instance"},
   {"xsd", "http://www.w3.org/2001/XMLSchema", \"http://www.w3.org/*/XMLSchema"},
   {"ns", "http://tempuri.org"},
   {NULL, NULL}
};

This file can be incorporated in the client/service application, see Section 9.4 for details on namespace mapping tables.
To deploy a Web service, copy the compiled CGI service application to the designated CGI directory of your Web server. Make sure the proper file permissions are set (chmod 755 calc.cgi for Unix/Linux). You can then publish the WSDL file on the Web by placing it in the appropriate Web server directory.
The gSOAP compiler also generates XML Schema files for all C/C++ complex types (e.g. structs and classes) when declared with a namespace prefix. These files are named ns.xsd, where ns is the namespace prefix used in the declaration of the complex type. The XML Schema files do not have to be published as the WSDL file already contains the appropriate XML Schema definitions.

7.2.9  Example

For example, suppose the following methods are defined in the header file:

typedef double xsd__double;
int ns__add(xsd__double a, xsd__double b, xsd__double &result);
int ns__sub(xsd__double a, xsd__double b, xsd__double &result);
int ns__sqrt(xsd__double a, xsd__double &result);

Then, one WSDL file will be created with the file name ns.wsdl that describes all three remote methods:

<?xml version="1.0" encoding="UTF-8"?>
<definitions name="Service"
   xmlns="http://schemas.xmlsoap.org/wsdl/"
   targetNamespace="http://location/Service.wsdl"
   xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
   xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
   xmlns:SOAP="http://schemas.xmlsoap.org/wsdl/soap/"
   xmlns:WSDL="http://schemas.xmlsoap.org/wsdl/"
   xmlns:xsd="http://www.w3.org/2000/10/XMLSchema"
   xmlns:tns="http://location/Service.wsdl"
   xmlns:ns="http://tempuri.org">
<types>
   <schema
      xmlns="http://www.w3.org/2000/10/XMLSchema"
      targetNamespace="http://tempuri.org"
      xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
      xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
      <complexType name="addResponse">
         <all>
            <element name="result" type="double" minOccurs="0" maxOccurs="1"/>
         </all>
         <anyAttribute namespace="##other"/>
      </complexType>
      <complexType name="subResponse">
         <all>
            <element name="result" type="double" minOccurs="0" maxOccurs="1"/>
         </all>
         <anyAttribute namespace="##other"/>
      </complexType>
      <complexType name="sqrtResponse">
         <all>
            <element name="result" type="double" minOccurs="0" maxOccurs="1"/>
         </all>
         <anyAttribute namespace="##other"/>
      </complexType>
   </schema>
</types>
<message name="addRequest">
   <part name="a" type="xsd:double"/>
   <part name="b" type="xsd:double"/>
</message>
<message name="addResponse">
   <part name="result" type="xsd:double"/>
</message>
<message name="subRequest">
   <part name="a" type="xsd:double"/>
   <part name="b" type="xsd:double"/>
</message>
<message name="subResponse">
   <part name="result" type="xsd:double"/>
</message>
<message name="sqrtRequest">
   <part name="a" type="xsd:double"/>
</message>
<message name="sqrtResponse">
   <part name="result" type="xsd:double"/>
</message>
<portType name="ServicePortType">
   <operation name="add">
      <input message="tns:addRequest"/>
      <output message="tns:addResponse"/>
   </operation>
   <operation name="sub">
      <input message="tns:subRequest"/>
      <output message="tns:subResponse"/>
   </operation>
   <operation name="sqrt">
      <input message="tns:sqrtRequest"/>
      <output message="tns:sqrtResponse"/>
   </operation>
</portType>
<binding name="ServiceBinding" type="tns:ServicePortType">
   <SOAP:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
   <operation name="add">
      <SOAP:operation soapAction="http://tempuri.org#add"/>
      <input>
         <SOAP:body use="encoded" namespace="http://tempuri.org"
            encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
      </input>
      <output>
         <SOAP:body use="encoded" namespace="http://tempuri.org"
            encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
      </output>
   </operation>
   <operation name="sub">
      <SOAP:operation soapAction="http://tempuri.org#sub"/>
      <input>
         <SOAP:body use="encoded" namespace="http://tempuri.org"
            encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
      </input>
      <output>
         <SOAP:body use="encoded" namespace="http://tempuri.org"
            encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
      </output>
   </operation>
   <operation name="sqrt">
      <SOAP:operation soapAction="http://tempuri.org#sqrt"/>
      <input>
         <SOAP:body use="encoded" namespace="http://tempuri.org"
            encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
      </input>
      <output>
         <SOAP:body use="encoded" namespace="http://tempuri.org"
            encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
      </output>
   </operation>
</binding>
<service name="Service">
   <port name="ServicePort" binding="tns:ServiceBinding">
      <SOAP:address location="http://location/Service.cgi"/>
   </port>
</service>
</definitions>

7.2.10  How to Parse and Import WSDL Service Descriptions to Develop Clients and Servers

Note: see README.txt in the wsdl directory for installation instructions for the WSDL parser and importer.
The creation of SOAP Web Services applications from a WSDL service description is a two-step process.
First, execute wsdl2h file.wsdl which generates the a C++ header file file.h (use wsdl2h -c file.wsdl to generate pure C code). You can provide a URL instead of a file name, when applicable. The generated header file is a Web service specification that contains the parameter types and service function definitions. The functions are represented as function prototypes. The file contains various annotations related to the Web service. The header file must be processed by the gSOAP compiler. You cannot use it with a C/C++ compiler directly.
Second, the header file file.h is processed by the gSOAP compiler by executing soapcpp2 -i file.h. This creates the C/C++ source files to build a client application, see 7.1. In addition, this generates a client proxy object declared in soapServiceProxy.h, where Service is the name of the service defined in the WSDL. To use this object, include the soapServiceProxy.h and Service.nsmap files in your C++ client application. The Service class provides the remote Web service methods as class members.
Consider the following example commands (entered at the command prompt):

$ wsdl2h -o XMethodsQuery.h http://www.xmethods.net/wsdl/query.wsdl
...
$ soapcpp2 -i XMethodsQuery.h

The first command generates XMethodsQuery.h from the WSDL at the specified URL. The header file is then processed by the gSOAP compiler to generate the stubs and skeletons. See XMethodsQuery.h for the types and service functions. A C++ client application may use the generated soapXMethodsQuerySoapProxy.h and soapXMethodsQuerySoapProxy.cpp class and XMethodsQuerySoap.nsmap XML namespace table to access the Web service. Both need to be #include-d in your source. Then compile and link the soapC.cpp and stdsoap2.cpp sources to complete the build.
When parsing a WSDL, the output file name is the WSDL input file name with extension .h instead of .wsdl. When an input file is absent or a WSDL file from a Web location is accessed, the header output will be produced on the standard output. Schema files (.xsd) can also be parsed and processed.
The wsdl2h command-line options are:

Option Description
-a generate indexed struct names for local elements with anonymous types
-c generate C source code
-d use DOM to populate xs:any and xsd:anyType elements
-e don't qualify enum names
This option is for backward compatibility with gSOAP 2.4.1 and earlier.
The option does not produce code that conforms to WS-I Basic Profile 1.0a.
-f generate flat C++ class hierarchy for schema extensions
-g generate global top-level element declarations
-h print help information
-I path use path to find files
-j don't generate SOAP_ENV__Header and SOAP_ENV__Detail definitions
-l include license information in output
-m use xsd.h module to import primitive types
-n name use name as the base namespace prefix name instead of ns
-N name use name as the base namespace prefix name for service namespaces
-o file output to file
-p create polymorphic types with C++ inheritance hierarchy with base xsd__anyType
This is automatically performed when WSDL contains polymorphic definitions
-q name use name for the C++ namespace for all service declarations
-r host:port connect via proxy host and port
-s don't generate STL code (no std::string and no std::vector)
-t file use type map file instead of the default file typemap.dat
-u don't generate unions
-v verbose output
-w always wrap response parameters in a response struct
-x don't generate _XML any/anyAttribute extensibility elements
-y generate typedef synonyms for structs and enums
-z generate pointer-based arrays for backward compatibility < gSOAP 2.7.6e
-_ don't generate _USCORE (replace with UNICODE _x005f)
-? print help information

7.2.11  The typemap.dat File

A typemap.dat file for wsdl2h contains custom XML Schema and C/C++ type bindings. An internal table is used by default.
An example typemap file is:

# This file contains custom definitions of the XML Schema types and
# C/C++ types for your project, and XML namespace prefix definitions.
# The wsdl2h WSDL importer consults this file to determine bindings.

[
// This comment will be included in the generated .h file
// You can include any additional declarations, includes, imports, etc.
// within [ ] sections. The brackets MUST appear at the start of a line
]
# XML namespace prefix definitions can be provided to override the
# default choice of ns1, ns2, ... prefixes. For example:

i = "http://www.soapinterop.org/"
s = "http://www.soapinterop.org/xsd"

# Type definitions are of the form: # type = declaration | use | pointer-use
# where
# type is the XML Schema type (or an application type in a namespace
# that has a prefix definition given as above).
# declaration is an optional C/C++ type declaration
# use is how the type is referred to in code
# pointer-use is how the type should be referred to as a pointer (opt)
# Example XML Schema and C/C++ type bindings:

xsd__int = | int
xsd__string = | char* | char*
xsd__boolean = enum xsd__boolean false_, true_ ; | enum xsd__boolean
xsd__base64Binary = class xsd__base64Binary unsigned char *__ptr; int __size; ; | xsd__base64Binary | xsd__base64Binary
# You can extend structs and classes with member data and functions.
# For example, adding a constructor to ns__myClass: ns__myClass = $ ns__myClass();
# The general form is # class_name = $ member;

The i and s prefixes are declared such that the header file output by the WSDL parser will use these to produce C/C++ code. XML Schema types are associated with an optional C/C++ type declaration, a use reference, and a pointer-use reference. The pointer-use reference of the xsd__byte type for example, is int* because char* is reserved for strings.

7.2.12  How to Use Client Functionalities Within a Service

A gSOAP service implemented with CGI may make direct client calls to other services from within its service operations, without setting up a new context. A stand-alone service application must setup a new soap struct context, e.g. using soap_copy and delete it after the call.
The server-side client call is best illustrated with an example. The following example is a more sophisticated example that combines the functionality of two Web services into one new SOAP Web service. The service provides a currency-converted stock quote. To serve a request, the service in turn requests the stock quote and the currency-exchange rate from two XMethods services.
In addition to being a client of two XMethods services, this service application can also be used as a client of itself to test the implementation. As a client invoked from the command-line, it will return a currency-converted stock quote by connecting to a copy of itself installed as a CGI application on the Web to retrieve the quote after which it will print the quote on the terminal.
The header file input to the gSOAP compiler is given below:

// Contents of file "quotex.h":
int ns1__getQuote(char *symbol, float &result); // XMethods delayed stock quote service remote method
int ns2__getRate(char *country1, char *country2, float &result); // XMethods currency-exchange service remote method
int ns3__getQuote(char *symbol, char *country, float &result); // the new currency-converted stock quote service

The quotex.cpp client/service application source is:

// Contents of file "quotex.cpp":
#include "soapH.h" // include generated proxy and SOAP support
int main(int argc, char **argv)
{
   struct soap soap;
   float q;
   soap_init(&soap);
   if (argc < = 2)
      soap_serve(&soap);
   else if (soap_call_ns3__getQuote(&soap, "http://www.cs.fsu.edu/~engelen/quotex.cgi", "", argv[1], argv[2], q))
      soap_print_fault(&soap, stderr);
   else 
      printf("\nCompany %s: %f (%s)\n", argv[1], q, argv[2]);
   return 0;
}
int ns3__getQuote(struct soap *soap, char *symbol, char *country, float &result)
{
   float q, r;
   int socket = soap->socket; // save socket (stand-alone service only, does not support keep-alive)
   if (soap_call_ns1__getQuote(soap, "http://services.xmethods.net/soap", "", symbol, &q) == 0 &&
      soap_call_ns2__getRate(soap, "http://services.xmethods.net/soap", NULL, "us", country, &r) == 0)
   {
      result = q*r;
      soap->socket = socket;
      return SOAP_OK;
   }
   soap->socket = socket;
   return SOAP_FAULT; // pass soap fault messages on to the client of this app
}
/* Since this app is a combined client-server, it is put together with
* one header file that describes all remote methods. However, as a consequence we
* have to implement the methods that are not ours. Since these implementations are
* never called (this code is client-side), we can make them dummies as below.
*/
int ns1__getQuote(struct soap *soap, char *symbol, float &result)
{ return SOAP_NO_METHOD; } // dummy: will never be called
int ns2__getRate(struct soap *soap, char *country1, char *country2, float &result)
{ return SOAP_NO_METHOD; } // dummy: will never be called

struct Namespace namespaces[] =
{
   {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"},
   {"SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/"},
   {"xsi", "http://www.w3.org/2001/XMLSchema-instance", "http://www.w3.org/*/XMLSchema-instance"},
   {"xsd", "http://www.w3.org/2001/XMLSchema", "http://www.w3.org/*/XMLSchema"},
   {"ns1", "urn:xmethods-delayed-quotes"},
   {"ns2", "urn:xmethods-CurrencyExchange"},
   {"ns3", "urn:quotex"},
   {NULL, NULL}
};

To compile:

soapcpp2 quotex.h
g++ -o quotex.cgi quotex.cpp soapC.cpp soapClient.cpp soapServer.cpp stdsoap2.cpp -lsocket -lxnet -lnsl

Note: under Linux and Mac OS X you can often omit the -l libraries.
The quotex.cgi executable is installed as a CGI application on the Web by copying it in the designated directory specific to your Web server. After this, the executable can also serve to test the service. For example

quotex.cgi IBM uk

returns the quote of IBM in uk pounds by communicating the request and response quote from the CGI application. See http://xmethods.com/detail.html?id=5 for details on the currency abbreviations.
When combining clients and service functionalities, it is required to use one header file input to the compiler. As a consequence, however, stubs and skeletons are available for all remote methods, while the client part will only use the stubs and the service part will use the skeletons. Thus, dummy implementations of the unused remote methods need to be given which are never called.
Three WSDL files are created by gSOAP: ns1.wsdl, ns2.wsdl, and ns3.wsdl. Only the ns3.wsdl file is required to be published as it contains the description of the combined service, while the others are generated as a side-effect (and in case you want to develop these separate services).

7.3  How to Use gSOAP for Asynchronous One-Way Message Passing

SOAP RPC client-server interaction is synchronous: the client blocks until the server responds to the request. gSOAP also supports asynchronous one-way message passing and the interoperable synchronous one-way message passing over HTTP. The two styles are similar, but only the latter is interoperable and is compliant to Basic Profile 1.0. The interoperable synchronous one-way message passing style over HTTP is discussed in Section 7.4 below.
SOAP messaging routines are declared as function prototypes, just like remote methods for SOAP RPC. However, the output parameter is a void type to indicate the absence of a return value.
For example, the following header file specifies a event message for SOAP messaging:

int ns__event(int eventNo, void);

The gSOAP stub and skeleton compiler generates the following functions in soapClient.cpp:

int soap_send_ns__event(struct soap *soap, const char URL, const char action, int event);
int soap_recv_ns__event(struct soap *soap, struct ns__event *dummy);

The soap_send_ns__event function transmits the message to the destination URL by opening a socket and sending the SOAP encoded message. The socket will remain open after the send and has to be closed with soap_closesock(). The open socket connection can also be used to obtain a service response, e.g. with a soap_recv function call.
The soap_recv_ns__event function waits for a SOAP message on the currently open socket (soap.socket) and fills the struct ns__event with the ns__event parameters (e.g. int eventNo). The struct ns__event is automatically created by gSOAP and is a mirror image of the ns__event parameters:

struct ns__event
{ int eventNo;
}

The gSOAP generated soapServer.cpp code includes a skeleton routine to accept the message. (The skeleton routine does not respond with a SOAP response message.)

int soap_serve_ns__event(struct soap *soap);

The skeleton routine calls the user-implemented ns__event(struct soap *soap, int eventNo) routine (note the absence of the void parameter!).
As usual, the skeleton will be automatically called by the remote method request dispatcher that handles both the remote method requests (RPCs) and messages:

main()
{ soap_serve(soap_new());
}
int ns__event(struct soap *soap, int eventNo)
{
   ... // handle event
   return SOAP_OK;
}

7.4  One-Way Message Passing over HTTP

One-way SOAP message passing over HTTP as defined by the SOAP specification and Basic Profile 1.0 is synchrounous, meaning that the server must respond with an HTTP OK header and an empty body. To implement synchrounous one-way messaging, the same setup for asynchrounous one-way messaing discussed in Section 7.3 is used, but with one simple addition at the client and server side.
At the server side, we need to return an empty HTTP OK response. This is accomplished as follows. For each one-way operation implemented in C/C++, we replace the return SOAP_OK with:

int ns__event(struct soap *soap, int eventNo)
{
   ... // handle event
   return soap_send_empty_response(soap, SOAP_OK); // SOAP_OK: return HTTP 202 ACCEPTED
}

At the client side, the empty response header must be parsed as follows:

if (soap_send_ns__event(soap, eventNo) != SOAP_OK
   || soap_recv_empty_response(soap) != SOAP_OK)
   soap_print_fault(soap, stderr);
...

The synchronous (and asynchronous) one-way messaging supports HTTP keep-alive and chunking.

7.5  How to Use the SOAP Serializers and Deserializers to Save and Load Application Data

The gSOAP stub and skeleton compiler generates serializers and deserializers for all user-defined data structures that are specified in the header file input to the compiler. The serializers and deserializers can be found in the generated soapC.cpp file. These serializers and deserializers can be used separately by an application without the need to build a full client or service application. This is useful for applications that need to save or export their data in XML or need to import or load data stored in XML format.
The following attributes can be set to control the destination and source for serialization and deserialization:

Variable Description
int soap.socket socket file descriptor for input and output or -1
ostream *soap.os (C++ only) output stream used for send operations
istream *soap.is (C++ only) input stream used for receive operations
int soap.sendfd when soap_socket < 0, this fd is used for send operations
int soap.recvfd when soap_socket < 0, this fd is used for receive operations

The following initializing and finalizing functions can be used:

Function Description
void soap_begin_send(struct soap*) start a send/write phase
int soap_end_send(struct soap*) flush the buffer
int soap_begin_recv(struct soap*) start a rec/read phase (if an HTTP header is present, parse it first)
int soap_end_recv(struct soap*) perform a id/href consistency check on deserialized data

These operations do not open or close the connections. The application should open and close connections or files and set the soap.socket, soap.os or soap.sendfd, soap.is or soap.recvfd streams or descriptors. When soap.socket < 0 and none of the streams and descriptors are set, then the standard input and output will be used.
See also Section 8.12 to control the I/O buffering and content encoding such as compression and DIME encoding.

7.5.1  Serializing a Data Type

To serialize a data type to a stream, two functions should be called to prepare for serialization of the data and to send the data, respectively. The first function, soap_serialize, analyzes pointers and determines if multi-references are required to encode the data and if cycles are present the object graph. The second function, soap_put, produces the XML output on a stream.
The soap_serialize and soap_put function names are specific to a data type. For example, soap_serialize_float(&soap, &d) is called to serialize an float value and soap_put_float(&soap, &d, "number", NULL) is called to output the floating point value in SOAP tagged with the name <number>. To initialize data, the soap_default function of a data type can be used. For example, soap_default_float(&soap, &d) initializes the float to 0.0. The soap_default functions are useful to initialize complex data types such as arrays, structs, and class instances. Note that the soap_default functions do not need the gSOAP runtime environment as a first parameter.
The following table lists the type naming conventions used by gSOAP:

Type Type Name
char* string
wchar_t* wstring
char byte
bool bool
double double
int int
float float
long long
LONG64 LONG64 (Win32)
long long LONG64 (Unix/Linux)
short short
time_t time
unsigned char unsignedByte
unsigned int unsignedInt
unsigned long unsignedLong
ULONG64 unsignedLONG64 (Win32)
unsigned long long unsignedLONG64 (Unix/Linux)
unsigned short unsignedShort
T[N] ArrayNOfType where Type is the type name of T
T* PointerToType where Type is the type name of T
struct Name Name
class Name Name
enum Name Name

Consider for example the following C code with a declaration of p as a pointer to a struct ns__Person:

struct ns__Person { char *name; } *p;

To serialize p, its address is passed to the function soap_serialize_PointerTons__Person generated for this type by the gSOAP compiler:

soap_serialize_PointerTons__Person(&soap, &p);

The address of p is passed, so the serializer can determine whether p was already serialized and to discover cycles in graph data structures. To generate the output, the address of p is passed to the function soap_put_PointerTons__Person together with the name of an XML element and an optional type string (to omit a type, use NULL):

soap_begin_send(&soap);
soap_put_PointerTons__Person(&soap, &p, "ns:element-name", "ns:type-name");
soap_end_send(&soap);

This produces:

<ns:element-name xmlns:SOAP-ENV="..." xmlns:SOAP-ENC="..." xmlns:ns="..."
   ... xsi:type="ns:type-name">
<name xsi:type="xsd:string">...</name>
</ns:element-name>

The serializer is initialized with the soap_begin_send(soap) function and closed with soap_end_send(soap). All temporary data structures and data structures deserialized on the heap are destroyed with the soap_destroy and soap_end functions (in this order).
The soap_done function should be used to reset the context, i.e. the last use of the context. To detach and deallocate the context, use soap_free.
To remove the temporary data only and keep the deserialized data on the heap, use soap_free_temp. Temporary data structures are only created if the encoded data uses pointers. Each pointer in the encoded data has an internal hash table entry to determine all multi-reference parts and cyclic parts of the complete data structure.
You can assign an output stream to soap.os or a file descriptor to soap.sendfd. For example

soap.sendfd = open(file, O_RDWR | O_CREAT, S_IWUSR | S_IRUSR);
soap_serialize_PointerTons__Person(&soap, &p);
soap_begin_send(&soap);
soap_put_PointerTons__Person(&soap, &p, "ns:element-name", "ns:type-name");
soap_end_send(&soap);

The soap_serialize function is optional. It MUST be used when the object graph contains cycles. It MUST be called to preserved the logical coherence of pointer-based data structures, where pointers may refer to co-referenced objects. By calling soap_serialize, data structures shared through pointers are serialized only once and referenced in XML using id-refs attributes. This actual id-refs used depend on the SOAP encoding. To turn off SOAP encoding, remove or avoid using the SOAP-ENV and SOAP-ENC namespace bindings in the namespace table. In addition, the SOAP_XML_TREE and SOAP_XML_GRAPH flags can be used to control the output.
To save the data as an XML tree (with one root) without any id-ref attributes, use the SOAP_XML_TREE flag. The data structure MUST NOT contain pointer-based cycles.
To preserve the exact structure of the data object graph and create XML with one root, use the SOAP_XML_GRAPH output-mode flag (see Section 8.12). Use this flag and the soap_serialize function to prepare the serialization of data with in-line id-ref attributes. Using the SOAP_XML_GRAPH flag assures the preservation of the logical structure of the data
For example, to encode the contents of two variables var1 and var2 that may share data throug pointer structures, the serializers are called before the output routines:

T1 var1;
T2 var2;
struct soap soap;
...
soap_init(&soap); // initialize
[soap_omode(&soap, flags);] // set output-mode flags (e.g. SOAP_ENC_XML|SOAP_ENC_ZLIB)
soap_begin(&soap); // start new (de)serialization phase
soap_set_omode(&soap, SOAP_XML_GRAPH);
soap_serialize_Type1(&soap, &var1);
soap_serialize_Type2(&soap, &var2);
...
[soap.socket = a_socket_file_descriptor;] // when using sockets
[soap.os = an_output_stream;] // C++
[soap.sendfd = an_output_file_descriptor;] // C
soap_begin_send(&soap);
soap_put_Type1(&soap, &var1, "[namespace-prefix:]element-name1", "[namespace-prefix:]type-name1");
soap_put_Type2(&soap, &var2, "[namespace-prefix:]element-name2", "[namespace-prefix:]type-name2");
...
soap_end_send(&soap); // flush
soap_destroy(&soap); // remove deserialized C++ objects
soap_end(&soap); // remove deserialized data structures
soap_done(&soap); // finalize last use of this environment
...

where Type1 is the type name of T1 and Type2 is the type name of T2 (see table above). The strings [namespace-prefix:]type-name1 and [namespace-prefix:]type-name2 describe the schema types of the elements. Use NULL to omit this type information.
For serializing class instances, method invocations MUST be used instead of function calls, for example obj.soap_serialize(&soap) and obj.soap_put(&soap, "elt", "type"). This ensures that the proper serializers are used for serializing instances of derived classes.
You can serialize a class instance to a stream as follows:

struct soap soap;
myClass obj;
soap_init(&soap); // initialize
soap_begin(&soap); // start new (de)serialization phase
soap_set_omode(&soap, SOAP_XML_GRAPH);
obj.serialize(&soap);
soap.os = cout; // send to cout
soap_begin_send(&soap);
obj.put(&soap, "[namespace-prefix:]element-name1", "[namespace-prefix:]type-name1");
...
soap_end_send(&soap); // flush
soap_destroy(&soap); // remove deserialized C++ objects
soap_end(&soap); // remove deserialized data
soap_done(&soap); // finalize last use of this environment

When you declare a soap struct pointer as a data member in a class, you can overload the << operator to serialize the class to streams:

ostream &operator<<(ostream &o, const myClass &e)
{
   if (!e.soap)
   ... error: need a soap struct to serialize (could use global struct) ...
   else 
   {
      ostream *os = e.soap->os;
      e.soap->os = &o;
      soap_set_omode(e.soap, SOAP_XML_GRAPH);       e.serialize(e.soap);
      soap_begin_send(e.soap);
      e.put(e.soap, "myClass", NULL);
      soap_end_send(e.soap);
      e.soap->os = os;
      soap_clr_omode(e.soap, SOAP_XML_GRAPH);
   }
   return o;
}

Of course, when you construct an instance you must set its soap struct to a valid environment. Deserialized class instances with a soap struct data member will have their soap structs set automatically, see Section 8.13.2.
In principle, XML output for a data structure can be produced with soap_put without calling the soap_serialize function first. In this case, the result is similar to SOAP_XML_TREE which means that no id-refs are output. Cycles in the data structure will crash the serialization algorithm, even when the SOAP_XML_GRAPH is set.
Consider the following struct:

// Contents of file "tricky.h":
struct Tricky
{
   int *p;
   int n;
   int *q;
};

The following fragment initializes the pointer fields p and q to the value of field n:

struct soap soap;
struct Tricky X;
X.n = 1;
X.p = &X.n;
X.q = &X.n;
soap_init(&soap);
soap_begin(&soap);
soap_serialize_Tricky(&soap, &X);
soap_put_Tricky(&soap, &X, "Tricky", NULL);
soap_end(&soap); // Clean up temporary data used by the serializer

What is special about this data structure is that n is 'fixed' in the Tricky structure, and p and q both point to n. The gSOAP serializers strategically place the id-ref attributes such that n will be identified as the primary data source, while p and q are serialized with ref/href attributes.
The resulting output is:

<Tricky xsi:type="Tricky">
<p href="#2"/> <n xsi:type="int">1</n> <q href="#2"/> <r xsi:type="int">2</r> </Tricky> <id id="2" xsi:type="int">1</id>

which uses an independent element at the end to represent the multi-referenced integer, assuming the SOAP-ENV and SOAP-ENC namespaces indicate SOAP 1.1 encoding.
With the SOAP_XML_GRAPH flag the output is:

<Tricky xsi:type="Tricky">
<p href="#2"/> <n id="2" xsi:type="int">1</n> <q href="#2"/> </Tricky>

In this case, the XML is self-contained and multi-referenced data is accurately serialized. The gSOAP generated deserializer for this data type will be able to accurately reconstruct the data from the XML (on the heap).

7.5.2  Deserializing a Data Type

To deserialize a data type, its soap_get function is used. The outline of a program that deserializes two variables var1 and var2 is for example:

T1 var1;
T2 var2;
struct soap soap;
...
soap_init(&soap); // initialize at least once
[soap_imode(&soap, flags);] // set input-mode flags
soap_begin(&soap); // begin new decoding phase
[soap.is = an_input_stream;] // C++
[soap.recvfd = an_input_file_desriptpr;] // C
soap_begin_recv(&soap); // if HTTP/MIME/DIME/GZIP headers are present, parse them
if (!soap_get_Type1(&soap, &var1, "[namespace-prefix:]element-name1", "[namespace-prefix:]type-name1"))
   ... error ...
if (!soap_get_Type2(&soap, &var2, "[namespace-prefix:]element-name2", "[namespace-prefix:]type-name1"))
   ... error ...
...
soap_end_recv(&soap); // check consistency of id/hrefs
soap_destroy(&soap); // remove deserialized C++ objects
soap_end(&soap); // remove deserialized data
soap_done(&soap); // finalize last use of the environment

The strings [namespace-prefix:]type-name1 and [namespace-prefix:]type-name2 are the schema types of the elements and should match the xsi:type attribute of the receiving message. To omit the match, use NULL as the type. For class instances, method invocation can be used instead of a function call if the object is already instantiated, i.e. obj.soap_get(&soap, "...", "...").
The soap_begin call resets the deserializers. The soap_destroy and soap_end calls remove the temporary data structures and the decoded data that was placed on the heap.
To remove temporary data while retaining the deserialized data on the heap, the function soap_free_temp should be called instead of soap_destroy and soap_end.
One call to the soap_get_Type function of a type Type scans the entire input to process its XML content and to capture SOAP 1.1 independent elements (which contain multi-referenced objects). As a result, soap.error will set to SOAP_EOF. Also storing multiple objects into one file will fail to decode them properly with multiple soap_get calls. A well-formed XML document should only have one root anyway, so don't save multiple objects into one file. If you must save multiple objects, create a linked list or an array of objects and save the linked list or array. You could use the soap_in_Type function instead of the soap_get_Type function. The soap_in_Type function parses one XML element at a time.
You can deserialize class instances from a stream as follows:

myClass obj;
struct soap soap;
soap_init(&soap); // initialize
soap_begin(&soap); // begin new decoding phase
soap.is = cin; // read from cin
soap_begin_recv(&soap); // if HTTP header is present, parse it
if (!obj.get(&soap, "myClass", NULL)
   ... error ...
soap_end_recv(&soap); // check consistency of id/hrefs
...
soap_destroy(&soap); // remove deserialized C++ objects
soap_end(&soap); // remove deserialized data
soap_done(&soap); // finalize last use of the environment

When you declare a soap struct pointer as a data member in a class, you can overload the >> operator to parse and deserialize a class instance from a stream:

istream &operator>>(istream &i, myClass &e)
{
   if (!e.soap)
   ... error: need soap struct to deserialize (could use global struct)...
   istream *is = e.soap->is;
   e.soap->is = &i;
   if (soap_begin_recv(e.soap) || e.in(e.soap, NULL, NULL) || soap_end_recv(e.soap))
      ... error ...
   e.soap->is = is;
   return i;
}

7.5.3  Example

As an example, consider the following data type declarations:

// Contents of file "person.h":
typedef char *xsd__string;
typedef char *xsd__Name;
typedef unsigned int xsd__unsignedInt;
enum ns__Gender {male, female};
class ns__Address
{
   public:
   xsd__string street;
   xsd__unsignedInt number;
   xsd__string city;
};
class ns__Person
{
   public:
   xsd__Name name;
   enum ns__Gender gender;
   ns__Address address;
   ns__Person *mother;
   ns__Person *father;
};

The following program uses these data types to write to standard output a data structure that contains the data of a person named "John" living at Downing st. 10 in Londen. He has a mother "Mary" and a father "Stuart". After initialization, the class instance for "John" is serialized and encoded in XML to the standard output stream using gzip compression (requires the Zlib library, compile sources with -DWITH_GZIP):

// Contents of file "person.cpp":
#include "soapH.h"
int main()
{
   struct soap soap;
   ns__Person mother, father, john;
   mother.name = "Mary";
   mother.gender = female;
   mother.address.street = "Downing st.";
   mother.address.number = 10;
   mother.address.city = "London";
   mother.mother = NULL;
   mother.father = NULL;
   father.name = "Stuart";
   father.gender = male;
   father.address.street = "Main st.";
   father.address.number = 5;
   father.address.city = "London";
   father.mother = NULL;
   father.father = NULL;
   john.name = "John";
   john.gender = male;
   john.address = mother.address;
   john.mother = &mother;
   john.father = &father;
   soap_init(&soap);
   soap_omode(&soap, SOAP_ENC_ZLIB | SOAP_XML_GRAPH); // see 8.12
   soap_begin(&soap);
   soap_begin_send(&soap);
   john.soap_serialize(&soap);
   john.soap_put(&soap, "johnnie", NULL);
   soap_end_send(&soap);
   soap_destroy(&soap);
   soap_end(&soap);
   soap_done(&soap);
}
struct Namespace namespaces[] =
{
   {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"},
   {"SOAP-ENC","http://schemas.xmlsoap.org/soap/encoding/"},
   {"xsi", "http://www.w3.org/2001/XMLSchema-instance"},
   {"xsd", "http://www.w3.org/2001/XMLSchema"},
   {"ns", "urn:person"}, // Namespace URI of the "Person" data type
   {NULL, NULL}
};

The header file is processed and the application compiled on Linux/Unix with:

soapcpp2 person.h
g++ -DWITH_GZIP -o person person.cpp soapC.cpp stdsoap2.cpp -lsocket -lxnet -lnsl -lz

(Depending on your system configuration, the libraries libsocket.a, libxnet.a, libnsl.a are required. Compiling on Linux typically does not require the inclusion of those libraries.) See 18.25 for details on compression with gSOAP.
Running the person application results in the compressed XML output:

<johnnie xsi:type="ns:Person" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
   xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:ns="urn:person"
   SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<name xsi:type="xsd:Name">John</name>
<gender xsi:type="ns:Gender">male</gender>
<address xsi:type="ns:Address">
<street id="3" xsi:type="xsd:string">Dowling st.</street>
<number xsi:type="unsignedInt">10</number>
<city id="4" xsi:type="xsd:string">London</city>
</address>
<mother xsi:type="ns:Person">
<name xsi:type="xsd:Name">Mary</name>
<gender xsi:type="ns:Gender">female</gender>
<address xsi:type="ns:Address">
<street href="#3"/>
<number xsi:type="unsignedInt">5</number>
<city href="#4"/>
</address>
</mother>
<father xsi:type="ns:Person">
<name xsi:type="xsd:Name">Stuart</name>
<gender xsi:type="ns:Gender">male</gender>
<address xsi:type="ns:Address">
<street xsi:type="xsd:string">Main st.</street>
<number xsi:type="unsignedInt">13</number>
<city href="#4"/>
</address>
</father>
</johnnie>

The following program fragment decodes this content from standard input and reconstructs the original data structure on the heap:

#include "soapH.h"
int main()
{
   struct soap soap;
   ns__Person *mother, *father, *john = NULL;
   soap_init(&soap);
   soap_imode(&soap, SOAP_ENC_ZLIB); // optional: gzip is detected automatically
   soap_begin(&soap);
   soap_begin_recv(&soap);
   if (soap_get_ns__Person(&soap, john, "johnnie", NULL) == NULL)
      ... error ...
   mother = john->mother;
   father = john->father;
   ...
   soap_end_recv(&soap);
   soap_free_temp(&soap); // Clean up temporary data but keep deserialized data
}
struct Namespace namespaces[] =
{
   {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"},
   {"SOAP-ENC","http://schemas.xmlsoap.org/soap/encoding/"},
   {"xsi", "http://www.w3.org/2001/XMLSchema-instance"},
   {"xsd", "http://www.w3.org/2001/XMLSchema"},
   {"ns", "urn:person"}, // Namespace URI of the "Person" data type
   {NULL, NULL}
};

It is REQUIRED to either pass NULL to the soap_get routine, or a valid pointer to a data structure that can hold the decoded content. The following example explicitly passes NULL:

   john = soap_get_ns__Person(&soap, NULL, "johnnie", NULL);

Note: the second NULL parameter indicates that the schema type attribute of the receiving message can be ignored. The deserializer stores the SOAP contents on the heap, and returns the address. The allocated storage is released with the soap_end call, which removes all temporary and deserialized data from the heap, or with the soap_free_temp call, which removes all temporary data only.
Alternatively, the XML content can be decoded within an existing allocated data structure. The following program fragment decodes the SOAP content in a struct ns__Person allocated on the stack:

#include "soapH.h"
main()
{
   struct soap soap;
   ns__Person *mother, *father, john;
   soap_init(&soap);
   soap_imode(&soap, SOAP_ENC_ZLIB); // optional
   soap_begin(&soap);
   soap_begin_recv(&soap);
   soap_default_ns__Person(&soap, &john);
   if (soap_get_ns__Person(&soap, &john, "johnnie", NULL) == NULL)
      ... error ...
   ...
}
struct Namespace namespaces[] =
   ...

Note the use of soap_default_ns__Person. This routine is generated by the gSOAP stub and skeleton compiler and assigns default values to the fields of john.

7.5.4  Serializing and Deserializing Class Instances to Streams

C++ applications can define appropriate stream operations on objects for (de)serialization of objects on streams. This is best illustrated with an example. Consider the class

class ns__person
{ public:
   char *name;
   struct soap *soap; // we need this, see below
   ns__person();
   ~ns__person();
};

The struct soap member is used to bind the instances to a gSOAP environment for (de)serialization. We use the gSOAP compiler from the command prompt to generate the class (de)serializers (assuming that person.h contains the class declaration):

soapcpp2 person.h

gSOAP generates the (de)serializers and an instantiation function for the class soap_new_ns__person(struct soap *soap, int array) to instantiate one or more objects and associate them with a gSOAP environment. The array parameter should be -1 to instantiate one object or should be the number of objects to instantiate as an array of objects.

#include "soapH.h"
#include "ns.nsmap"
...
struct soap *soap = soap_new();
ns__person *p = soap_new_ns__person(soap, -1);
...
cout << p; // serialize p in XML
...
in >> p; // parse XML and deserialize p
...
soap_destroy(soap); // deletes p too
soap_end(soap);
soap_done(soap);

The stream operations are implemented as follows

ostream &operator<<(ostream &o, const ns__person &p)
{
   if (!p.soap)
      return o; // need a gSOAP environment to serialize
   p.soap->os = &o;
   soap_omode(p.soap, SOAP_XML_GRAPH); // XML tree or graph
   p.soap_serialize(p.soap);
   soap_begin_send(p.soap);
   if (p.soap_put(p.soap, "person", NULL)
       | | soap_end_send(p.soap))
      ; // handle I/O error
   return o;
}
istream &operator>>(istream &i, ns__person &p)
{
   if (!p.soap)
      return o; // need a gSOAP environment to parse XML and deserialize
   p.soap->is = &i;
   if (soap_begin_recv(p.soap)
       | | p.soap_in(p.soap, NULL, NULL)
       | | soap_end_recv(p.soap))
      ; // handle I/O error
   return i;
}

7.5.5  How to Specify Default Values for Omitted Data

The gSOAP compiler generates soap_default functions for all data types. The default values of the primitive types can be easily changed by defining any of the following macros in the stdsoap2.h file:

#define SOAP_DEFAULT_bool
#define SOAP_DEFAULT_byte
#define SOAP_DEFAULT_double
#define SOAP_DEFAULT_float
#define SOAP_DEFAULT_int
#define SOAP_DEFAULT_long
#define SOAP_DEFAULT_LONG64
#define SOAP_DEFAULT_short
#define SOAP_DEFAULT_string
#define SOAP_DEFAULT_time
#define SOAP_DEFAULT_unsignedByte
#define SOAP_DEFAULT_unsignedInt
#define SOAP_DEFAULT_unsignedLong
#define SOAP_DEFAULT_unsignedLONG64
#define SOAP_DEFAULT_unsignedShort
#define SOAP_DEFAULT_wstring

Instead of adding these to stdsoap2.h, you can also compile with option -DWITH_SOAPDEFS_H and include your definitions in file userdefs.h. The absence of a data value in a receiving SOAP message will result in the assignment of a default value to a primitive type upon deserialization.
Default values can also be assigned to individual struct and class fields of primitive type. For example,

struct MyRecord
{
   char *name = "Unknown";
   int value = 9999;
   enum Status { active, passive } status = passive;
}

Default values are assigned to the fields on receiving a SOAP/XML message in which the data values are absent.
Because method requests and responses are essentially structs, default values can also be assigned to method parameters. The default parameter values do not control the parameterization of C/C++ function calls, i.e. all actual parameters must be present when calling a function. The default parameter values are used in case an inbound request or response message lacks the XML elements with parameter values. For example, a Web service can use default values to fill-in absent parameters in a SOAP/XML request:

int ns__login(char *uid = "anonymous", char *pwd = "guest", bool granted);

When the request message lacks uid and pwd parameters, e.g.:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
   xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
   xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:ns="http://tempuri.org">
   <SOAP-ENV:Body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
      <ns:login>
      </ns:login>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

then the service uses the default values. In addition, the default values will show up in the SOAP/XML request and response message examples generated by the gSOAP compiler.

8  Using the gSOAP Stub and Skeleton Compiler

The gSOAP stub and skeleton compiler is invoked from the command line and optionally takes the name of a header file as an argument or, when the file name is absent, parses the standard input:

soapcpp2 [aheaderfile.h]

where aheaderfile.h is a standard C++ header file. The compiler acts as a preprocessor and produces C++ source files that can be used to build SOAP client and Web service applications in C++. The files generated by the compiler are:

File Name Description
soapStub.h A modified and annotated header file produced from the input header file
soapH.h Main header file to be included by all client and service sources
soapC.cpp Serializers and deserializers for the specified data structures
soapClient.cpp Client stub routines for remote operations
soapServer.cpp Service skeleton routines
soapClientLib.cpp Client stubs combined with local static (de)serializers
soapServerLib.cpp Service skeletons combined with local static (de)serializers
soapXYZProxy.h A C++ proxy object (link with soapC.cpp soapClient.cpp)
soapXYZProxy.h With option -i: proxy object (link with soapC.cpp and soapXYZProxy.cpp)
soapXYZProxy.cpp With option -i: proxy code
soapXYZObject.h A C++ server object (link with soapC.cpp and soapServer.cpp)
soapXYZService.h With option -i: server object (link with soapC.cpp and soapXYZService.cpp)
soapXYZService.cpp With option -i: server code
.xsd An ns.xsd file is generated with an XML Schema for each namespace prefix ns used by a data structure in the header file input to the compiler, see Section 7.2.8
.wsdl A ns.wsdl file is generated with an WSDL description for each namespace prefix ns used by a remote method in the header file input to the compiler, see Section 7.2.8
.xml Several SOAP/XML request and response files are generated. These are example message files are valid provided that sufficient schema namespace directives are added to the header file or the generated .nsmap namespace table for the client/service is not modified by hand
.nsmap A ns.nsmap file is generated for each namespace prefix ns used by a remote method in the header file input to the compiler, see Section 7.2.8. The file contains a namespace mapping table that can be used in the client/service sources

Both client and service applications are developed from a header file that specifies the remote methods. If client and service applications are developed with the same header file, the applications are guaranteed to be compatible because the stub and skeleton routines use the same serializers and deserializers to encode and decode the parameters. Note that when client and service applications are developed together, an application developer does not need to know the details of the internal SOAP encoding used by the client and service.
The soapClientLib.cpp and soapServerLib.cpp can be used to build (dynamic) client and server libraries. The serialization routines are local (static) to avoid link symbol conflicts. You must create a separate library for SOAP Header and Fault handling, as described in Section 18.34.
The following files are part of the gSOAP package and are required to build client and service applications:

File Name Description
stdsoap2.h Header file of stdsoap2.cpp runtime library
stdsoap2.c Runtime C library with XML parser and run-time support routines
stdsoap2.cpp Runtime C++ library identical to stdsoap2.c

8.1  Compiler Options

The compiler supports the following options:

Option Description
-1 Use SOAP 1.1 namespaces and encodings (default)
-2 Use SOAP 1.2 namespaces and encodings
-C Generate client-side code only
-S Generate server-side code only
-L Do not generate soapClientLib/soapServerLib
-a use value of SOAPAction HTTP header to dispatch method at server side
-c Generate pure C code
-d < path > Save sources in directory specified by < path >
-e Generate SOAP RPC encoding style bindings
-h Print a brief usage message
-i Generate service proxies and objects inherited from soap struct
-I < path > Use < path > (or paths separated with `:') for #import
-l Generate linkable modules (experimental)
-m Generate Matlabtm code for MEX compiler
-n When used with -p, enables multi-client and multi-server builds:
Sets compiler option WITH_NONAMESPACES, see Section 8.11
Saves the namespace mapping table with name < name > _namespaces instead of namespaces
Renames soap_serve() into < name > _serve() and soap_destroy() into < name > _destroy()
-p < name > Save sources with file name prefix < name > instead of "soap"
-s Generates deserialization code with strict XML validation checks
-t Generates code to send typed messages (with the xsi:type attribute)
-v Display version info
-w Do not generate WSDL and schema files
-x Do not generate sample XML message files

For example

soapcpp2 -cd '../projects' -pmy file.h

Saves the sources:

../projects/myH.h
../projects/myC.c
../projects/myClient.c
../projects/myServer.c
../projects/myStub.h

MS Windows users can use the usual "/" for options, for example:

soapcpp2 /cd '..\projects' /pmy file.h

Compiler options c, i, n, l, w can be set in the gSOAP header file using the //gsoapopt directive. For example,

// Generate pure C and do not produce WSDL output:
//gsoapopt cw
int ns__myMethod(char*,char**); // takes a string and returns a string

8.2  SOAP 1.1 Versus SOAP 1.2

gSOAP supports SOAP 1.1 by default. SOAP 1.2 support is automatically turned on when the appropriate SOAP 1.2 namespace is used in the namespace mapping table:

struct Namespace namespaces[] =
{
   {"SOAP-ENV", "http://www.w3.org/2002/06/soap-envelope"},
   {"SOAP-ENC", "http://www.w3.org/2002/06/soap-encoding"},
   {"xsi", "http://www.w3.org/2001/XMLSchema-instance", "http://www.w3.org/*/XMLSchema-instance"},
   {"xsd", "http://www.w3.org/2001/XMLSchema", "http://www.w3.org/*/XMLSchema"},    ...
}

gSOAP Web services and clients can automatically switch from SOAP 1.1 to SOAP 1.2 by providing the SOAP 1.2 namespace as a pattern in the third column of a namespace table:

struct Namespace namespaces[] =
{
   {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/", "http://www.w3.org/2002/06/soap-encoding"},
   {"SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/", "http://www.w3.org/2002/06/soap-envelope"},
   {"xsi", "http://www.w3.org/2001/XMLSchema-instance", "http://www.w3.org/*/XMLSchema-instance"},
   {"xsd", "http://www.w3.org/2001/XMLSchema", "http://www.w3.org/*/XMLSchema"},    ...
}

This way, gSOAP Web services can respond to either SOAP 1.1 or SOAP 1.2 requests. gSOAP will automatically return SOAP 1.2 responses for SOAP 1.2 requests.
The gSOAP soapcpp2 compiler generates a .nsmap file with SOAP-ENV and SOAP-ENC namespace patterns similar to the above. Since clients issue a send first, they will always use SOAP 1.1 for requests when the namespace table is similar as shown above. Clients can accept SOAP 1.2 responses by inspecting the response message. To restrict gSOAP services and clients to SOAP 1.2 and to generate SOAP 1.2 service WSDLs, use soapcpp2 compiler option -2 to generate SOAP 1.2 conformant .nsmap and .wsdl files.
Caution: SOAP 1.2 does not support partially transmitted arrays. So the __offset field of a dynamic array is meaningless.
Caution: SOAP 1.2 requires the use of SOAP_ENV__Code, SOAP_ENV__Reason, and SOAP_ENV__Detail fields in a SOAP_ENV__Fault fault struct, while SOAP 1.1 uses faultcode, faultstring, and detail fields. Use soap_receiver_fault_subcode(struct soap *soap, const char *subcode, const char *faultstring, const char *detail) to set a SOAP 1.1/1.2 fault at the server-side with a fault subcode (SOAP 1.2). Use soap_sender_fault_subcode(struct soap *soap, const char *subcode, const char *faultstring, const char *detail) to set a SOAP 1.1/1.2 unrecoverable Bad Request fault at the server-side with a fault subcode (SOAP 1.2).

8.3  The soapdefs.h Header File

The soapdefs.h header file is included in stdsoap2.h when compiling with option -DWITH_SOAPDEFS_H:

g++ -DWITH_SOAPDEFS_H -c stdsoap2.cpp

The soapdefs.h file allows users to include definitions and add includes without requiring changes to stdsoap2.h. For example,

// Contents of soapdefs.h
#include < ostream >
#define SOAP_BUFLEN 20480 // use large send/recv buffer

The following header file can now refer to ostream:

extern class ostream; // ostream can't be (de)serialized, but need to be declared to make it visible to gSOAP
class ns__myClass
{ ...
   virtual void print(ostream &s) const; // need ostream here
   ...
};

See also Section 18.3.

8.4  How to Build Modules and Libraries with the gSOAP #module Directive

The #module directive is used to build modules. A library can be build from a module and linked with multiple Web services applications. The directive should appear at the top of the header file and has the following formats:

#module "name"

and

#module "name" "fullname"

where name must be a unique short name for the module. The name is case insensitive and MUST not exceed 4 characters in length. The fullname, when present, represents the full name of the module.
The rest of the content of the header file includes type declarations and optionally the declarations of remote methods and SOAP Headers/Faults. When the gSOAP compiler processes the header file module, it will generate the source codes for a library. The Web services application that uses the library should use a header file that imports the module with the #import directive.
For example:

/* Contents of module.h */
#module "test"
long;
char*;
struct ns__S
{ ... }

The module.h header file declares a long, char*, and a struct ns__X. The module name is "test", so the gSOAP compiler produces a testC.cpp file with the (de)serializers for these types. The testC.cpp library can be separately compiled and linked with an application that is built from a header file that imports "module.h" using #import "module.h". You should also compile testClient.cpp when you want to build a library that includes the remote methods that you defined in the module header file.
A module MUST be imported into another header file to use it and you cannot use a module alone to build a SOAP or XML application. That is, the top most header file in the import tree SHOULD NOT be a module.
When multiple modules are linked, the types that they declare MUST be declared in one module only to avoid name clashes and link errors. You cannot create two modules that share the same type declaration and link the modules. When necessary, you should consider creating a module hierarchy such that types are declared only once and by only one module when these modules must be linked.

8.5  How to use the gSOAP #import Directive

The #import directive is used to include gSOAP header files into other gSOAP header files for processing with the gSOAP compiler soapcpp2. The C #include directive cannot be used to include gSOAP header files. The #include directive is reserved to control the post-gSOAP compilation process, see 8.6.
The #import directive is used for two purposes: you can use it to include the contents of a header file into another header file and you can use it to import a module, see 8.4.
An example of the #import directive:

#import "mydefs.gsoap"
int ns__mymethod(xsd__string in, xsd__int *out);

where "mydefs.gsoap" is a gSOAP header file that defines xsd__string and xsd__int:

typedef char *xsd__string;
typedef int xsd__int;

8.6  How to Use #include and #define Directives

The #include and #define directives are normally ignored by the gSOAP compiler. The use of the directives is enabled with the -i option of the gSOAP compiler, see Section 8.1. However, the gSOAP compiler will not actually parse the contents of the header files provided by the #include directives in a header file. Instead, the #include and #define directives will be added to the generated soapH.h header file before any other header file is included. Therefore, #include and #define directives can be used to control the C/C++ compilation process of the sources of an application.
The following example header file refers to ostream by including < ostream > :

#include < ostream >
#define WITH_COOKIES // use HTTP cookie support (you must compile stdsoap2.cpp with -DWITH_COOKIES)
#define WITH_OPENSSL // enable HTTPS (SSL) support (you must compile stdsoap2.cpp with -DWITH_OPENSSL)
#define SOAP_DEFAULT_float FLT_NAN // use NaN instead of 0.0
extern class ostream; // ostream can't be (de)serialized, but need to be declared to make it visible to gSOAP
class ns__myClass
{ ...
   virtual void print(ostream &s) const; // need ostream here
   ...
};

This example also uses #define directives for various settings.
Caution: Note that the use of #define in the header file does not automatically result in compiling stdsoap2.cpp with these directives. You MUST use the -DWITH_COOKIES and -DWITH_OPENSSL options when compiling stdsoap2.cpp before linking the object file with your codes. As an alternative, you can use #define WITH_SOAPDEFS_H and put the #define directives in the soapdefs.h file.

8.7  Compiling a gSOAP Client

After invoking the gSOAP stub and skeleton compiler on a header file description of a service, the client application can be compiled on a Linux machine as follows:

g++ -o myclient myclient.cpp stdsoap2.cpp soapC.cpp soapClient.cpp

Or on a Unix machine:

g++ -o myclient myclient.cpp stdsoap2.cpp soapC.cpp soapClient.cpp -lsocket -lxnet -lnsl

(Depending on your system configuration, the libraries libsocket.a, libxnet.a, libnsl.a or dynamic *.so versions of those libraries are required.)
The myclient.cpp file must include soapH.h and must define a global namespace mapping table. A typical client program layout with namespace mapping table is shown below:

// Contents of file "myclient.cpp"
#include "soapH.h";
...
// A remote method invocation:
   soap_call_some_remote_method(...);
...
struct Namespace namespaces[] =
{   // {"ns-prefix", "ns-name"}
   {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"},
   {"SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/"},
   {"xsi", "http://www.w3.org/2001/XMLSchema-instance"},
   {"xsd", "http://www.w3.org/2001/XMLSchema"},
   {"ns1", "urn:my-remote-method"},
   {NULL, NULL}
};
...

A mapping table is generated by the gSOAP compiler that can be used in the source, see Section 7.2.8.

8.8  Compiling a gSOAP Web Service

After invoking the gSOAP stub and skeleton compiler on a header file description of the service, the server application can be compiled on a Linux machine as follows:

g++ -o myserver myserver.cpp stdsoap2.cpp soapC.cpp soapServer.cpp

Or on a Unix machine:

g++ -o myserver myserver.cpp stdsoap2.cpp soapC.cpp soapServer.cpp -lsocket -lxnet -lnsl

(Depending on your system configuration, the libraries libsocket.a, libxnet.a, libnsl.a or dynamic *.so versions of those libraries are required.)
The myserver.cpp file must include soapH.h and must define a global namespace mapping table. A typical service program layout with namespace mapping table is shown below:

// Contents of file "myserver.cpp"
#include "soapH.h";
int main()
{
   soap_serve(soap_new());
}
...
// Implementations of the remote methods as C++ functions
...
struct Namespace namespaces[] =
{   // {"ns-prefix", "ns-name"}
   {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"},
   {"SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/"},
   {"xsi", "http://www.w3.org/2001/XMLSchema-instance"},
   {"xsd", "http://www.w3.org/2001/XMLSchema"},
   {"ns1", "urn:my-remote-method"},
   {NULL, NULL}
};
...

When the gSOAP service is compiled and installed as a CGI application, the soap_serve function acts as a service dispatcher. It listens to standard input and invokes the method via a skeleton routine to serve a SOAP client request. After the request is served, the response is encoded in SOAP and send to standard output. The method must be implemented in the server application and the type signature of the method must be identical to the remote method specified in the header file. That is, the function prototype in the header file must be a valid prototype of the method implemented as a C/C++ function.

8.9  Using gSOAP for Creating Web Services and Clients in Pure C

The gSOAP compiler can be used to create pure C Web services and clients. The gSOAP stub and skeleton compiler soapcpp2 generates .cpp files by default. The compiler generates .c files with the -c option. However, these files only use C syntax and data types if the header file input to soapcpp2 uses C syntax and data types. For example:

soapcpp2 -c quote.h
gcc -o quote quote.c stdsoap2.c soapC.c soapClient.c

Warnings will be issued by the compiler when C++ class declarations occur in the header file.

8.10  Limitations of gSOAP

gSOAP is SOAP 1.1 and SOAP 1.2 compliant and supports SOAP RPC and document/literal operations.
From the perspective of the C/C++ language, a few C++ language features are not supported by gSOAP and these features cannot be used in the specification of SOAP remote methods.
There are certain limitations for the following C++ language constructs:
STL and STL templates
The gSOAP compiler supports STL strings std::string and std::wstring (see Section 10.3.6) and the STL containers std::deque, std::list, std::vector, and std::set, (see Section 10.11.8).
Templates
The gSOAP compiler is a preprocessor that cannot determine the template instantations used by the main program, nor can it generate templated code. You can however implement containers similar to the STL containers.
Multiple inheritance
Single class inheritance is supported. Multiple inheritance cannot be supported due to limitations of the SOAP protocol.
Abstract methods
A class must be instantiatable to allow decoding of instances of the class.
Directives
Directives and pragmas such as #include and #define are interpreted by the gSOAP compiler. However, the interpretation is different compared to the usual handling of directives, see Section 8.6. If necessary, a traditional C++ preprocessor can be used for the interpretation of directives. For example, Unix and Linux users can use "cpp -B" to expand the header file, e.g. cpp -B myfile.h - soapcpp2. Use the gSOAP #import directive to import gSOAP header files, see 8.5.
C and C++ programming statements
All class methods of a class should be declared within the class declaration in the header file, but the methods should not be implemented in code. All class method implementations must be defined within another C++ source file and linked to the application.
The following data types require some attention to ensure they are serialized:
union types
A union data type can not be serialized unless run-time information is associated with a union in a struct/class as discussed in Section 10.7. An alternative is to use a struct with a pointer type for each field. Because NULL pointers are not encoded, the resulting encoding will appear as a union type if only one pointer field is valid (i.e. non-NULL) at the time that the data type is encoded.
void and void* types
The void data type cannot be serialized unless run-time type information is associated with the pointer using a int __type field in the struct/class that contains the void*. The void* data type is typically used to point to some object or to some array of some type of objects at run-time. The compiler cannot determine the type of data pointed to and the size of the array pointed to. A struct or class with a void* field can be augmented to support the (de)serialization of the void* using a int __type field as described in Section 10.9.
Pointers to sequences of elements in memory
Any pointer, except for C strings which are pointers to a sequence of characters, are treated by the compiler as if the pointer points to only one element in memory at run-time. Consequently, the encoding and decoding routines will ignore any subsequent elements that follow the first in memory. For the same reason, arrays of undetermined length, e.g. float a[] cannot be used. gSOAP supports dynamic arrays using a special type convention, see Section 10.11.
Uninitialized pointers
Obviously, all pointers that are part of a data structure must be valid or NULL to enable serialization of the data structure at run time.
There are a number of programming solutions that can be adopted to circumvent these limitations. Instead of using void*, a program can in some cases be modified to use a pointer to a known type. If the pointer is intended to point to different types of objects, a generic base class can be declared and the pointer is declared to point to the base class. All the other types are declared to be derived classes of this base class. For pointers that point to a sequence of elements in memory dynamic arrays should be used instead, see 10.11.

8.11  Compile Time Flags

The following macros (#defines) can be used to enable certain optional features:

Macro Description
WITH_SOAPDEFS_H includes the soapdefs.h file for custom settings, see Section 8.3
WITH_COOKIES enables HTTP cookies, see Sections 18.26 18.27
WITH_OPENSSL enables OpenSSL, see Sections 18.20 18.19
WITH_IPV6 enables IPv6 support
WITH_TCPFIN use TCP FIN after sends when socket is ready to close
WITH_FASTCGI enables FastCGI, see Sections 18.29
WITH_GZIP enables gzip and deflate compression, see Section 18.25
WITH_ZLIB enables deflate compression only, see Section 18.25
WITH_UDP enables UDP support (SOAP-over-UDP), see Section 17
WITH_FAST (obsolete)
WITH_NOIO eliminates need for file IO and BSD socket library, see Section 18.31
WITH_NOHTTP eliminates HTTP stack to reduce code size
WITH_LEAN creates a small-footprint executable, see Section 18.30
WITH_LEANER creates an even smaller footprint executable, see Section 18.30
WITH_NONAMESPACESomit initialization of soap struct with global namespaces table
and you MUST explicitly initialize soap.namespaces to point to a table
see also Section 9.4
WITH_NOEMPTYSTRUCT inserts a dummy member in empty structs to enable compilation
WITH_NOGLOBAL omit SOAP Header and Fault serialization code
WITH_CDATA retain the parsed CDATA sections in literal XML strings (no conversion)
WITH_CASEINSENSITIVETAGS enable case insensitive XML parsing

Caution: it is important that the macros MUST be consistently defined to compile the sources, such as stdsoap2.cpp, soapC.cpp, soapClient.cpp, soapServer.cpp, and all application sources that include stdsoap2.h or soapH.h. If the macros are not consistently used, the application will crash due to a mismatches in the declaration and access of the gSOAP environment.

8.12  Run Time Flags

gSOAP provides flags to control the input and output mode settings at runtime. These flags are divided into four categories: transport (IO), content encoding (ENC), XML marshalling (XML), and C/C++ data mapping (C).
Although gSOAP is fully SOAP 1.1 compliant, some SOAP implementations may have trouble accepting multi-reference data and/or require explicit nil data so these flags can be used to put gSOAP in "safe mode". In addition, the embedding (or inlining) of multi-reference data is adopted in the SOAP 1.2 specification, which gSOAP automatically supports when handling with SOAP 1.2 messages. The flags are:

Flag Description
SOAP_IO_FLUSH Disable buffering and flush output (default for all file-based output)
SOAP_IO_BUFFER Enable buffering (default for all socket-oriented connections)
SOAP_IO_STORE Store entire message to calculate HTTP content length
SOAP_IO_CHUNK Use HTTP chunking
SOAP_IO_LENGTH Internal flag: require apriori calculation of content length
SOAP_IO_KEEPALIVE Attempt to keep socket connections alive (open)
SOAP_IO_UDP Use UDP (datagram) transport, maximum message length is SOAP_BUFLEN
SOAP_ENC_XML Use plain XML encoding without HTTP headers (useful with SOAP_ENC_ZLIB)
SOAP_ENC_DIME Use DIME encoding (automatic when DIME attachments are used)
SOAP_ENC_MIME Use MIME encoding (activate using soap_set_mime)
SOAP_ENC_MTOM Use MTOM XOP attachments (instead of DIME)
SOAP_ENC_ZLIB Compress encoding with Zlib (deflate or gzip format)
SOAP_ENC_SSL Encrypt encoding with SSL (automatic with "https:" endpoints)
SOAP_XML_INDENT Produce indented XML output
SOAP_XML_CANONICAL Produce canonical XML output
SOAP_XML_STRICT XML strict validation
SOAP_XML_TREE Serialize data as XML trees (no multi-ref, duplicate data when necessary)
SOAP_XML_GRAPH Serialize data as an XML graph with inline multi-ref (SOAP 1.2 default)
SOAP_XML_NIL Serialize NULL data as xsi:nil elements (omit by default)
SOAP_C_NOIOB Do not fault with SOAP_IOB
SOAP_C_UTFSTRING (De)serialize 8-bit strings "as is" (strings MUST have UTF-8 encoded content)
SOAP_C_MBSTRING Activate multibyte character support (depends on locale)
SOAP_C_NILSTRING Serialize empty strings as nil (ommited element)

The flags can be selectively turned on/off at any time, for example when multiple Web services are accessed by a client that require special treatment.
All flags are orthogonal, except SOAP_IO_FLUSH, SOAP_IO_BUFFER, SOAP_IO_STORE, and SOAP_IO_CHUNK which are enumerations and only one of these I/O flags can be used. Also the XML serialization flags SOAP_XML_TREE and SOAP_XML_GRAPH should not be mixed.
The flags control the inbound and outbound message transport, encoding, and (de)serialization. The following functions are used to set and reset the flags for input and output modes:

Function Description
soap_init2(struct soap *soap, int imode, int omode) Initialize the runtime and set flags
soap_imode(struct soap *soap, int imode) Set all input mode flags
soap_omode(struct soap *soap, int omode) Set all output mode flags
soap_set_imode(struct soap *soap, int imode) Enable input mode flags
soap_set_omode(struct soap *soap, int omode) Enable output mode flags
soap_clr_imode(struct soap *soap, int omode) Disable input mode flags
soap_clr_omode(struct soap *soap, int omode) Disable output mode flags

The default setting is SOAP_IO_DEFAULT for both input and output modes.
For example

struct soap soap;
soap_init2(&soap, SOAP_IO_KEEPALIVE,
   SOAP_IO_KEEPALIVE | SOAP_ENC_ZLIB | SOAP_XML_TREE | SOAP_XML_CANONICAL);
if (soap_call_ns__myMethod(&soap, ...))
...

sends a compressed client request with keep-alive enabled and all data serialized as canonical XML trees.
In many cases, setting the input mode will have no effect, especially with HTTP transport because gSOAP will determine the optimal input buffering and the encoding used for an inbound message. The flags that have an effect on handling inbound messages are SOAP_IO_KEEPALIVE, SOAP_ENC_SSL (but automatic when "https:" endpoints are used or soap_ssl_accept), SOAP_C_NOIOB, SOAP_C_UTFSTRING, and SOAP_C_MBSTRING.
Caution: The SOAP_XML_TREE serialization flag can be used to improve interoperability with SOAP implementations that are not fully SOAP 1.1 compliant. However, a tree serialization will duplicate data when necessary and will crash the serializer for cyclic data structures.

8.13  Memory Management

Understanding gSOAP's run-time memory management is important to optimize client and service applications by eliminating memory leaks and/or dangling references.
There are two forms of dynamic (heap) allocations made by gSOAP's runtime for serialization and deserialization of data. Temporary data is created by the runtime such as hash tables to keep pointer reference information for serialization and hash tables to keep XML id/href information for multi-reference object deserialization. Deserialized data is created upon receiving SOAP messages. This data is stored on the heap and requires several calls to the malloc library function to allocate space for the data and new to create class instances. All such allocations are tracked by gSOAP's runtime by linked lists for later deallocation. The linked list for malloc allocations uses some extra space in each malloced block to form a chain of pointers through the malloced blocks. A separate malloced linked list is used to keep track of class instance allocations.
gSOAP does not enforce a deallocation policy and the user can adopt a deallocation policy that works best for a particular application. As a consequence, deserialized data is never deallocated by the gSOAP runtime unless the user explicitly forces deallocation by calling functions to deallocate data collectively or individually.
The deallocation functions are:

Function Call Description
soap_destroy(struct soap *soap) Remove all dynamically allocated C++ objects.
must be called before soap_end()
soap_end(struct soap *soap) Remove temporary data and deserialized data except
class instances
soap_free_temp(struct soap *soap) Instead of soap_destroy and soap_end:
remove temporary data only
soap_dealloc(struct soap *soap, void *p) Remove malloced data at p. When p==NULL: remove all
dynamically allocated (deserialized) data except class instances
soap_delete(struct soap *soap, void *p) Remove class instance at p. When p==NULL: remove all
dynamically allocated (deserialized) class instances
(this is identical to calling soap_destroy(struct soap *soap))
soap_unlink(struct soap *soap, void *p) Unlink data/object at p from gSOAP's deallocation chain
so gSOAP won't deallocate it
soap_done(struct soap *soap) Detach context (reset runtime environment)
soap_free(struct soap *soap) Detach and free context (allocated with soap_new)

Temporary data (i.e. the hash tables) are automatically removed with calls to the soap_free_temp function which is made within soap_end and soap_done or when the next call to a stub or skeleton routine is made to send a message or receive a message. Deallocation of non-class based data is straightforward: soap_end removes all dynamically allocated deserialized data (data allocated with soap_malloc. That is, when the client/service application does not use any class instances that are (de)marshalled, but uses structs, arrays, etc., then calling the soap_end function is safe to remove all deserialized data. The function can be called after processing the deserialized data of a remote method call or after a number of remote method calls have been made. The function is also typically called after soap_serve, when the service finished sending the response to a client and the deserialized client request data can be removed.
Individual data objects can be unlinked from the deallocation chain if necessary, to prevent deallocation by the collective soap_end or soap_destroy functions.

8.13.1  Memory Management Policies

There are three situations to consider for memory deallocation policies for class instances:
  1. the program code deletes the class instances and the class destructors in turn SHOULD delete and free any dynamically allocated data (deep deallocation) without calling the soap_end and soap_destroy functions,
  2. or the class destructors SHOULD NOT deallocate any data and the soap_end and soap_destroy functions can be called to remove the data.
  3. or the class destructors SHOULD mark their own deallocation and mark the deallocation of any other data deallocated by it's destructors by calling the soap_unlink function. This allows soap_destroy and soap_end to remove the remaining instances and data without causing duplicate deallocations.
It is advised to use pointers to class instances that are used within other structs and classes to avoid the creation of temporary class instances during deserialization. The problem with temporary class instances is that the destructor of the temporary may affect data used by other instances through the sharing of data parts accessed with pointers. Temporaries and even whole copies of class instances can be created when deserializing SOAP multi-referenced objects. A dynamic array of class instances is similar: temporaries may be created to fill the array upon deserialization. To avoid problems, use dynamic arrays of pointers to class instances. This also enables the exchange of polymorphic arrays when the elements are instances of classes in an inheritance hierarchy. In addition, allocate data and class instances with soap_malloc and soap_new_X functions (more details below).
To summarize, it is advised to pass class data types by pointer to a remote method. For example:

class X { ... };
ns__remoteMethod(X *in, ...);

Response elements that are class data types can be passed by reference, as in:

class X { ... };
class ns__remoteMethodResponse { ... };
ns__remoteMethod(X *in, ns__remoteMethodResponse &out);

But dynamic arrays declared as class data types should use a pointer to a valid object that will be overwritten when the function is called, as in:

typedef int xsd__int;
class X { ... };
class ArrayOfint { xsd__int *__ptr; int __size; };
ns__remoteMethod(X *in, ArrayOfint *out);

Or a reference to a valid or NULL pointer, as in:

typedef int xsd__int;
class X { ... };
class ArrayOfint { xsd__int *__ptr; int __size; };
ns__remoteMethod(X *in, ArrayOfint *&out);

The gSOAP memory allocation functions can be used in client and/or service code to allocate temporary data that will be automatically deallocated. These functions are:

Function Call Description
void *soap_malloc(struct soap *soap, size_t n) return pointer to n bytes
Class *soap_new_Class(struct soap *soap, int n) instantiate n Class objects

The soap_new_X functions are generated by the gSOAP compiler for every class X in the header file. Parameter n MUST be -1 to instantiate a single object, or larger or equal to 0 to instantiate an array of n objects.
Space allocated with soap_malloc will be released with the soap_end and soap_dealloc functions. Objects instantiated with soap_new_X(struct soap*) are removed altogether with soap_destroy(struct soap*). Individual objects instantiated with soap_new_X are removed with soap_delete_X(struct soap*, X*). For example, the following service uses temporary data in the remote method implementation:

int main()
{ ...
   struct soap soap;
   soap_init(&soap);
   soap_serve(&soap);
   soap_end(&soap);
   ...
}

An example remote method that allocates a temporary string is:

int ns__itoa(struct soap *soap, int i, char **a)
{
   *a = (char*)soap_malloc(soap, 11);
   sprintf(*a, "%d", i);
   return SOAP_OK;
}

This temporary allocation can also be used to allocate strings for the SOAP Fault data structure. For example:

int ns__mymethod(...)
{ ...
   if (exception)
   {
      char *msg = (char*)soap_malloc(soap, 1024); // allocate temporary space for detailed message
      sprintf(msg, "...", ...); // produce the detailed message
      return soap_receiver_fault(soap, Än exception occurred", msg); // return the server-side fault
   }
   ...
}

Use soap_receiver_fault(struct soap *soap, const char *faultstring, const char *detail) to set a SOAP 1.1/1.2 fault at the server-side. Use soap_sender_fault(struct soap *soap, const char *faultstring, const char *detail) to set a SOAP 1.1/1.2 unrecoverable Bad Request fault at the server-side. Sending clients are not supposed to retry messages after a Bad Request, while errors at the receiver-side indicate temporary problems.
The above functions do not include a SOAP 1.2 Subcode element. To include Subcode element, use soap_receiver_fault_subcode(struct soap *soap, const char *subcode, const char *faultstring, const char *detail) to set a SOAP 1.1/1.2 fault with Subcode at the server-side. Use soap_sender_fault_subcode(struct soap *soap, const char *subcode, const char *faultstring, const char *detail) to set a SOAP 1.1/1.2 unrecoverable Bad Request fault with Subcode at the server-side.
gSOAP provides a function to duplicate a string into gSOAP's memory space:

char *soap_strdup(struct soap *soap, const char *s)

The function allocates space for s with soap_malloc, copies the string, and returns a pointer to the duplicated string. When s is NULL, the function does not allocate and copy the string and returns NULL.

8.13.2  Intra-Class Memory Management

When a class declaration has a struct soap * field, this field will be set to point to the current gSOAP run-time environment by gSOAP's deserializers and by the soap_new_Class functions. This simplifies memory management for class instances. The struct soap* pointer is implicitly set by the gSOAP deserializer for the class or explicitly by calling the soap_new_X function for class X. For example:

class Sample
{ public:
   struct soap *soap; // reference to gSOAP's run-time
   ...
   Sample();
   ~Sample();
};

The constructor and destructor for class Sample are:

Sample::Sample()
{ this->soap = NULL;
}
Sample::~Sample()
{ soap_unlink(this->soap, this);
}

The soap_unlink() call removes the object from gSOAP's deallocation chain. In that way, soap_destroy can be safely called to remove all class instances. The following code illustrates the explicit creation of a Sample object and cleanup:

struct soap *soap = soap_new(); // new gSOAP runtime
Sample *obj = soap_new_Sample(soap, -1); // new Sample object with obj->soap set to runtime
...
delete obj; // also calls soap_unlink to remove obj from the deallocation chain
soap_destroy(soap); // deallocate all (other) class instances
soap_end(soap); // clean up

Here is another example:

class ns__myClass
{ ...
   struct soap *soap; // set by soap_new_ns__myClass()
   char *name;
   void setName(const char *s);
   ...
};

Calls to soap_new_ns__myClass(soap, n) will set the soap field in the class instance to the current gSOAP environment. Because the deserializers invoke the soap_new functions, the soap field of the ns__myClass instances are set as well. This mechanism is convenient when Web Service methods need to return objects that are instantiated in the methods. For example

int ns__myMethod(struct soap *soap, ...)
{
   ns__myClass *p = soap_new_ns__myClass(soap, -1);
   p->setName("SOAP");
   return SOAP_OK;
}
void ns__myClass::ns__setName(const char *s)
{
   if (soap)
      name = (char*)soap_malloc(soap, strlen(s)+1);
   else 
      name = (char*)malloc(strlen(s)+1);
   strcpy(name, s);
}
ns__myClass::ns__myClass()
{
   soap = NULL;
   name = NULL;
}
ns__myClass::~ns__myClass()
{
   if (!soap && name) free(name);
   soap_unlink(soap, this);
}

Calling soap_destroy right after soap_serve in the Web Service will destroy all dynamically allocated class instances.

8.14  Debugging

To activate message logging for debugging, un-comment the #define DEBUG directive in stdsoap2.h. Compile the client and/or server applications as described above (or simply use g++ -DDEBUG ... to compile with debugging activated). When the client and server applications run, they will log their activity in three separate files:

File Description
SENT.log The SOAP content transmitted by the application
RECV.log The SOAP content received by the application
TEST.log A log containing various activities performed by the application

Caution: The client and server applications may run slow due to the logging activity.
Caution: When installing a CGI application on the Web with debugging activated, the log files may sometimes not be created due to file access permission restrictions imposed on CGI applications. To get around this, create empty log files with universal write permissions. Be careful about the security implication of this.
You can test a service CGI application without deploying it on the Web. To do this, create a client application for the service and activate message logging by this client. Remove any old SENT.log file and run the client (which connects to the Web service or to another dummy, but valid address) and copy the SENT.log file to another file, e.g. SENT.tst. Then redirect the SENT.tst file to the service CGI application. For example,

myservice.cgi < SENT.tst

This should display the service response on the terminal.
The file names of the log files and the logging activity can be controlled at the application level. This allows the creation of separate log files by separate services, clients, and threads. For example, the following service logs all SOAP messages (but no debug messages) in separate directories:

struct soap soap;
soap_init(&soap);
...
soap_set_recv_logfile(&soap, "logs/recv/service12.log"); // append all messages received in /logs/recv/service12.log
soap_set_sent_logfile(&soap, "logs/sent/service12.log"); // append all messages sent in /logs/sent/service12.log
soap_set_test_logfile(&soap, NULL); // no file name: do not save debug messages
...
soap_serve(&soap);
...

Likewise, messages can be logged for individual client-side remote method calls.

8.15  Required Libraries

9  The gSOAP Remote Method Specification Format

A SOAP remote method is specified as a C/C++ function prototype in a header file. The function is REQUIRED to return int, which is used to represent a SOAP error code, see Section 9.2. Multiple remote methods MAY be declared together in one header file.
The general form of a SOAP remote method specification is:

[int] [namespace_prefix__]method_name([inparam1, inparam2, ...,] outparam);

where
namespace_prefix__
is the optional namespace prefix of the method (see identifier translation rules 9.3)
method_name
it the remote method name (see identifier translation rules 9.3)
inparam
is the declaration of an input parameter of the remote method
outparam
is the declaration of the output parameter of the remote method
This simple form can only pass a single, non-struct and non-class type output parameter. See 9.1 for passing multiple output parameters. The name of the declared function namespace_prefix__ method_name must be unique and cannot match the name of a struct, class, or enum declared in the same header file.
The method request is encoded in SOAP as an XML element and the namespace prefix, method name, and input parameters are encoded using the format:

<[namespace-prefix:]method_name xsi:type="[namespace-prefix:]method_name>
<inparam-name1 xsi:type="...">...</inparam-name1>
<inparam-name2 xsi:type="...">...</inparam-name2>
...
</[namespace-prefix:]method_name>

where the inparam-name accessors are the element-name representations of the inparam parameter name declarations, see Section 9.3. (The optional parts are shown enclosed in [].)
The XML response by the Web service is of the form:

<[namespace-prefix:]method-nameResponse xsi:type="[namespace-prefix:]method-nameResponse>
<outparam-name xsi:type="...">...</outparam-name>
</[namespace-prefix:]method-nameResponse>

where the outparam-name accessor is the element-name representation of the outparam parameter name declaration, see Section 9.3. By convention, the response element name is the method name ending in Response. See 9.1 on how to change the declaration if the service response element name is different.
The gSOAP stub and skeleton compiler generates a stub routine for the remote method. This stub is of the form:

int soap_call_[namespace_prefix__]method_name(struct soap *soap, char *URL, char *action, [inparam1, inparam2, ...,] outparam);

This proxy can be called by a client application to perform the remote method call.
The gSOAP stub and skeleton compiler generates a skeleton routine for the remote method. The skeleton function is:

int soap_serve_[namespace_prefix__]method_name(struct soap *soap);

The skeleton routine, when called by a service application, will attempt to serve a request on the standard input. If no request is present or if the request does not match the method name, SOAP_NO_METHOD is returned. The skeleton routines are automatically called by the generated soap_serve routine that handles all requests.

9.1  Remote Method Parameter Passing

The input parameters of a remote method MUST be passed by value. Input parameters cannot be passed by reference with the & reference operator, but an input parameter value MAY be passed by a pointer to the data. Of course, passing a pointer to the data is preferred when the size of the data of the parameter is large. Also, to pass instances of (derived) classes, pointers to the instance need to be used to avoid passing the instance by value which requires a temporary and prohibits passing derived class instances. When two input parameter values are identical, passing them using a pointer has the advantage that the value will be encoded only once as multi-reference (hence, the parameters are aliases). When input parameters are passed using a pointer, the data pointed to will not be modified by the remote method and returned to the caller.
The output parameter MUST be passed by reference using & or by using a pointer. Arrays are passed by reference by default and do not require the use of the reference operator &.
The input and output parameter types have certain limitations, see Section 8.10
If the output parameter is a struct or class type, it is considered a SOAP remote method response element instead of a simple output parameter value. That is, the name of the struct or class is the name of the response element and the struct or class fields are the output parameters of the remote method, see also 7.1.7. Hence, if the output parameter has to be a struct or class, a response struct or class MUST be declared as well. In addition, if a remote method returns multiple output parameters, a response struct or class MUST be declared. By convention, the response element is the remote method name ending with "Response".
The general form of a response element declaration is:

struct [namespace_prefix__]response_element_name
{
   outparam1;
   outparam2;
   ...
};

where
namespace_prefix__
is the optional namespace prefix of the response element (see identifier translation rules 9.3)
response_element_name
it the name of the response element (see identifier translation rules 9.3)
outparam
is the declaration of an output parameter of the remote method
The general form of a remote method specification with a response element declaration for (multiple) output parameters is:

[int] [namespace_prefix__]method_name([inparam1, inparam2, ...,] struct [namespace_prefix__]response_element_name {outparam1[, outparam2, ...]} &anyparam);

The choice of name for anyparam has no effect on the SOAP encoding and decoding and is only used as a place holder for the response.
The method request is encoded in SOAP as an independent element and the namespace prefix, method name, and input parameters are encoded using the format:

<[namespace-prefix:]method-name xsi:type="[namespace-prefix:]method-name>
<inparam-name1 xsi:type="...">...</inparam-name1>
<inparam-name2 xsi:type="...">...</inparam-name2>
...
</[namespace-prefix:]method-name>

where the inparam-name accessors are the element-name representations of the inparam parameter name declarations, see Section 9.3. (The optional parts resulting from the specification are shown enclosed in [].)
The method response is expected to be of the form:

<[namespace-prefix:]response-element-name xsi:type="[namespace-prefix:]response-element-name>
<outparam-name1 xsi:type="...">...</outparam-name1>
<outparam-name2 xsi:type="...">...</outparam-name2>
...
</[namespace-prefix:]response-element-name>

where the outparam-name accessors are the element-name representations of the outparam parameter name declarations, see Section 9.3. (The optional parts resulting from the specification are shown enclosed in [].)
The input and/or output parameters can be made anonymous, which allows the deserialization of requests/responses with different parameter names as is endorsed by the SOAP 1.1 specification, see Section 7.1.13.

9.2  Error Codes

The error codes returned by the stub and skeleton routines are listed below.

Code Description
SOAP_OK No error
SOAP_CLI_FAULT* The service returned a client fault (SOAP 1.2 Sender fault)
SOAP_SVR_FAULT* The service returned a server fault (SOAP 1.2 Receiver fault)
SOAP_TAG_MISMATCH An XML element didn't correspond to anything expected
SOAP_TYPE An XML Schema type mismatch
SOAP_SYNTAX_ERROR An XML syntax error occurred on the input
SOAP_NO_TAG Begin of an element expected, but not found
SOAP_IOB Array index out of bounds
SOAP_MUSTUNDERSTAND* An element needs to be ignored that need to be understood
SOAP_NAMESPACE Namespace name mismatch (validation error)
SOAP_OBJ_MISMATCH Mismatch in the size and/or shape of an object
SOAP_FATAL_ERROR Internal error
SOAP_FAULT An exception raised by the service
SOAP_NO_METHOD The dispatcher did not find a matching operation for the request
SOAP_NO_DATA No data in HTTP message
SOAP_GET_METHOD HTTP GET operation not handled, see Section 18.10
SOAP_EOM Out of memory
SOAP_NULL An element was null, while it is not supposed to be null
SOAP_MULTI_ID Multiple occurrences of the same element ID on the input
SOAP_MISSING_ID Element ID missing for an HREF on the input
SOAP_HREF Reference to object is incompatible with the object refered to
SOAP_UDP_ERROR Message too large to store in UDP packet
SOAP_TCP_ERROR A connection error occured
SOAP_HTTP_ERROR An HTTP error occured
SOAP_SSL_ERROR An SSL error occured
SOAP_ZLIB_ERROR A Zlib error occured
SOAP_PLUGIN_ERROR Failed to register plugin
SOAP_MIME_ERROR MIME parsing error
SOAP_DIME_ERROR DIME parsing error
SOAP_DIME_END End of DIME error
SOAP_DIME_HREF DIME attachment has no href from SOAP body
(and no DIME callbacks were defined to save the attachment)
SOAP_DIME_MISMATCH DIME version/transmission error
SOAP_VERSIONMISMATCH* SOAP version mismatch or no SOAP message
SOAP_DATAENCODINGUNKNOWN SOAP 1.2 DataEncodingUnknown fault
SOAP_REQUIRED Attributed required validation error
SOAP_PROHIBITED Attributed prohibited validation error
SOAP_OCCURS Element minOccurs/maxOccurs validation error
SOAP_LENGTH Element length validation error
SOAP_EOF Unexpected end of file, no input, or timeout while receiving data

The error codes that are returned by a stub routine (proxy) upon receiving a SOAP Fault from the server are marked (*). The remaining error codes are generated by the proxy itself as a result of problems with a SOAP payload. The error code is SOAP_OK when the remote method call was successful (the SOAP_OK predefined constant is guaranteed to be 0). The error code is also stored in soap.error, where soap is a variable that contains the current runtime environment. The function soap_print_fault(struct soap *soap, FILE *fd) can be called to display an error message on fd where current value of the soap.error variable is used by the function to display the error. The function soap_print_fault_location(struct soap *soap, FILE *fd) prints the location of the error if the error is a result from parsing XML. Use soap_sprint_fault(struct soap*, char *buf, size_t len) to print the error to a string.
A remote method implemented in a SOAP service MUST return an error code as the function's return value. SOAP_OK denotes success and SOAP_FAULT denotes an exception. The exception details can be assigned with the soap_receiver_fault(struct soap *soap, const char *faultstring, const char *detail) which sets the strings soap.fault->faultstring and soap.fault->detail for SOAP 1.1, and soap.fault->SOAP_ENV__Reason and soap.fault->SOAP_ENV__Detail for SOAP 1.2, where soap is a variable that contains the current runtime environment, see Section 11. A receiver error indicates that the service can't handle the request, but can possibly recover from the error. To return an unrecoverable error, use soap_receiver_fault(struct soap *soap, const char *faultstring, const char *detail).
To return a HTTP error code a service method can simply return the HTTP error code number. For example, return 404; returns a "404 Not Found" HTTP error back to the client. The soap.error is set to the HTTP error code at the client side. The HTTP 1.1 error codes are:

# Error
201 Created
202 Accepted
203 Non-Authoritative Information
204 No Content
205 Reset Content
206 Partial Content
300 Multiple Choices
301 Moved Permanently
302 Found
303 See Other
304 Not Modified
305 Use Proxy
307 Temporary Redirect
400 Bad Request
401 Unauthorized
402 Payment Required
403 Forbidden
404 Not Found
405 Method Not Allowed
406 Not Acceptable
407 Proxy Authentication Required
408 Request Time-out
409 Conflict
410 Gone
411 Length Required
412 Precondition Failed
413 Request Entity Too Large
414 Request-URI Too Large
415 Unsupported Media Type
416 Requested range not satisfiable
417 Expectation Failed
500 Internal Server Error
501 Not Implemented
502 Bad Gateway
503 Service Unavailable
504 Gateway Time-out
505 HTTP Version not supported

The error codes are given for informational purposes only. The HTTP protocol requires the proper actions after an error is issued. gSOAP's HTTP 1.0/1.1 handling is automatic.

9.3  C/C++ Identifier Name to XML Name Translations

One of the "secrets" behind the power and flexibility of gSOAP's encoding and decoding of remote method names, class names, type identifiers, and struct or class fields is the ability to specify namespace prefixes with these names that are used to denote their encoding style. More specifically, a C/C++ identifier name of the form

[namespace_prefix__]element_name

will be encoded in XML as

<[namespace-prefix:]element-name ...>

The underscore pair (__) separates the namespace prefix from the element name. Each namespace prefix has a namespace URI specified by a namespace mapping table 9.4, see also Section 7.1.2. The namespace URI is a unique identification that can be associated with the remote methods and data types. The namespace URI disambiguates potentially identical remote method names and data type names used by disparate organizations.
XML element names are NCNames (restricted strings) that MAY contain hyphens, dots, and underscores. The special characters in the XML element names of remote methods, structs, classes, typedefs, and fields can be controlled using the following conventions: A single underscore in a namespace prefix or identifier name is replaced by a hyphen (-) in the XML element name. For example, the identifier name SOAP_ENC__ur_type is represented in XML as SOAP-ENC:ur-type. The sequence _DOT is replaced by a dot (.), and the sequence _USCORE is replaced by an underscore (_) in the corresponding XML element name. For example:

class n_s__biz_DOTcom
{
   char *n_s__biz_USCOREname;
};

is encoded in XML as:

<n-s:biz.com xsi:type="n-s:biz.com">
   <n-s:biz_name xsi:type="string">Bizybiz</n-s:biz_name>
</n-s:biz.com>

Trailing underscores of an identifier name are not translated into the XML representation. This is useful when an identifier name clashes with a C++ keyword. For example, return is often used as an accessor name in a SOAP response element. The return element can be specified as return_ in the C++ source code. Note that XML should be treated as case sensitive, so the use of e.g. Return may not always work to avoid a name clash with the return keyword. The use of trailing underscores also allows for defining structs and classes with essentially the same XML Schema type name, but that have to be distinguished as seperate C/C++ types.
For decoding, the underscores in identifier names act as wildcards. An XML element is parsed and matches the name of an identifier if the name is identical to the element name (case insensitive) and the underscores in the identifier name are allowed to match any character in the element name. For example, the identifier name I_want__soap_fun_the_bea___DOTcom matches the element name I-want:SOAP4fun@the-beach.com.

9.4  Namespace Mapping Table

A namespace mapping table MUST be defined by clients and service applications. The mapping table is used by the serializers and deserializers of the stub and skeleton routines to produce a valid SOAP payload and to validate an incoming SOAP payload. A typical mapping table is shown below:

struct Namespace namespaces[] =
{   // {"ns-prefix", "ns-name"}
   {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"}, // MUST be first
   {"SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/"}, // MUST be second
   {"xsi", "http://www.w3.org/2001/XMLSchema-instance"}, // MUST be third
   {"xsd", "http://www.w3.org/2001/XMLSchema"}, // Required for XML Schema types
   {"ns1", "urn:my-service-URI"}, // The namespace URI of the remote methods
   {NULL, NULL} // end of table
};

Each namespace prefix used by a identifier name in the header file specification (see Section 9.3) MUST have a binding to a namespace URI in the mapping table. The end of the namespace mapping table MUST be indicated by the NULL pair. The namespace URI matching is case insensitive. A namespace prefix is distinguished by the occurrence of a pair of underscores (__) in an identifier.
An optional namespace pattern MAY be provided with each namespace mapping table entry. The patterns provide an alternative namespace matching for the validation of decoded SOAP messages. In this pattern, dashes (-) are single-character wildcards and asterisks (*) are multi-character wildcards. For example, to decode different versions of XML Schema type with different authoring dates, four dashes can be used in place of the specific dates in the namespace mapping table pattern:

struct Namespace namespaces[] =
{   // {"ns-prefix", "ns-name", "ns-name validation pattern"}
...
   {"xsi", "http://www.w3.org/2001/XMLSchema-instance", "http://www.w3.org/----/XMLSchema-instance"},
   {"xsd", "http://www.w3.org/2001/XMLSchema", "http://www.w3.org/----/XMLSchema"},
...

Or alternatively, asterisks can be used as wildcards for multiple characters:

struct Namespace namespaces[] =
{   // {"ns-prefix", "ns-name", "ns-name validation pattern"}
...
   {"xsi", "http://www.w3.org/2001/XMLSchema-instance", "http://www.w3.org/*/XMLSchema-instance"},
   {"xsd", "http://www.w3.org/2001/XMLSchema", "http://www.w3.org/*/XMLSchema"},
...

A namespace mapping table is automatically generated together with a WSDL file for each namespace prefix that is used for a remote method in the header file. This namespace mapping table has entries for all namespace prefixes. The namespace URIs need to be filled in. These appear as http://tempuri.org in the table. See Section 18.2 on how to specify the namespace URIs in the header file.
For decoding elements with namespace prefixes, the namespace URI associated with the namespace prefix (through the xmlns attribute of an XML element) is searched from the beginning to the end in a namespace mapping table, and for every row the following tests are performed as part of the validation process:
  1. the string in the second column matches the namespace URI (case insensitive)
  2. the string in the optional third column matches the namespace URI (case insensitive), where - is a one-character wildcard and * is a multi-character wildcard
When a match is found, the namespace prefix in the first column of the table is considered semantically identical to the namespace prefix used by the XML element to be decoded, though the prefix names may differ. A service will respond with the namespace that it received from a client in case it matches a pattern in the third column.
For example, let's say we have the following structs:

struct a__elt { ... };
struct b__elt { ... };
struct k__elt { ... };

and a namespace mapping table in the program:

struct Namespace namespaces[] =
{   // {"ns-prefix", "ns-name", "ns-name validation pattern"}
...
   {"a", "some uri"},
   {"b", "other uri"},
   {"c", "his uri", "* uri"},
...

Then, the following XML elements will match the structs:

<n:elt xmlns:n="some URI">       matches the struct name a__elt
...
<m:elt xmlns:m="other URI">       matches the struct name b__elt
...
<k:elt xmlns:k="my URI">       matches the struct name c__elt
...

The response of a service to a client request that uses the namespaces listed above, will include my URI for the name space of element k.
It is possible to use a number of different namespace tables and select the one that is appropriate. For example, an application might contact many different Web services all using different namespace URIs. If all the URIs are stored in one table, each remote method invocation will dump the whole namespace table in the SOAP payload. There is no technical problem with that, but it can be ugly when the table is large. To use different namespace tables, declare a pointer to a table and set the pointer to a particular table before remote method invocation. For example:

struct Namespace namespacesTable1[] = { ... };
struct Namespace namespacesTable2[] = { ... };
struct Namespace namespacesTable3[] = { ... };
struct Namespace *namespaces;
...
struct soap soap;
...
soap_init(&soap);
soap_set_namespaces(&soap, namespaceTable1);
soap_call_remote_method(&soap, URL, Action, ...);
...

10  gSOAP Serialization and Deserialization Rules

This section describes the serialization and deserialization of C and C++ data types for SOAP 1.1 and 1.2 compliant encoding and decoding.

10.1  SOAP RPC Encoding Versus Document/Literal and xsi:type Info

The wsdl2h tool automatically generates a header file specialized for SOAP RPC encoding or document/literal style. The serialization and deserialization rules for C/C++ objects is almost identical for these styles, except for the following important issues.
With SOAP RPC encoding style, care must be taken to ensure typed messages are produced for interoperability and compatibility reasons. To ensure that the gSOAP engine automatically generates typed (xsi:type attributed) messages, use soapcpp2 option -t, see also Section 8.1. While gSOAP can handle untyped messages, some toolkits fail to find deserializers when the xsi:type information is absent.
When starting the development of a gSOAP application from a header file, the soapcpp2 compiler will generate WSDL and schema files for SOAP 1.1 document/literal style by default (use the //gsoap directives to control this, see Section 18.2). Use soapcpp2 options -2, -e, and -t to generate code for SOAP 1.2, RPC encoding, and typed messages.
With SOAP RPC encoding, generic complexTypes with maxOccurs=ünbounded" are not allowed and SOAP encoded arrays must be used. Also XML attributes and unions (XML schema choice) are not allowed with SOAP RPC encoding.
Also with SOAP RPC encoding, multi-reference accessors are common to encode co-referenced objects and object digraphs. Multi-reference encoding is not supported in document/literal style, which means that cyclic object digraphs cannot be serialized (the engine will crash). Also DAGs are represented as XML trees in document/literal style messaging.

10.2  Primitive Type Encoding

The default encoding rules for the primitive C and C++ data types are given in the table below:

Type XSD Type
bool boolean
char* (C string) string
char byte
long double decimal (with #import "custom/long_double.h")
double double
float float
int int
long long
LONG64 long
long long long
short short
time_t dateTime
struct tm dateTime (with #import "custom/struct_tm.h")
unsigned char unsignedByte
unsigned int unsignedInt
unsigned long unsignedLong
ULONG64 unsignedLong
unsigned long long unsignedLong
unsigned short unsignedShort
wchar_t* string

Objects of type void and void* cannot be encoded. Enumerations and bit masks are supported as well, see 10.4.

10.3  How to Encode and Decode Primitive Types as XSD Types

By default, encoding of the primitive types will take place as per SOAP encoding style. The encoding can be changed to any XML Schema type (XSD type) with an optional namespace prefix by using a typedef in the header file input to the gSOAP stub and skeleton compiler. The declaration enables the implementation of built-in XML Schema types (also known as XSD types) such as positiveInteger, xsd:anyURI, and xsd:date for which no built-in data structures in C and C++ exist but which can be represented using standard data structures such as strings, integers, and floats.
The typedef declaration is frequently used for convenience in C. A typedef declares a type name for a (complex) type expression. The type name can then be used in other declarations in place of the more complex type expression, which often improves the readability of the program code.
The gSOAP compiler interprets typedef declarations the same way as a regular C compiler interprets them, i.e. as types in declarations. In addition however, the gSOAP compiler will also use the type name in the encoding of the data in SOAP. The typedef name will appear as the XML element name of an independent element and as the value of the xsi:type attribute in the SOAP payload.
Many built-in primitive and derived XSD types such as xsd:anyURI, positiveInteger, and decimal can be stored by standard primitive data structures in C++, such as strings, integers, floats, and doubles. To serialize strings, integers, floats, and doubles as built-in primitive and derived XSD types, a typedef declaration can be used to declare an XSD type.
For example, the declaration

typedef unsigned int xsd__positiveInteger;

creates a named type positiveInteger which is represented by unsigned int in C++. For example, the encoding of a positiveInteger value 3 is

<positiveInteger xsi:type="xsd:positiveInteger">3</positiveInteger>

The built-in XML Schema datatype hierarchy from the XML Schema Part 2 documentation http://www.w3.org/TR/xmlschema-2 is depicted below.
Figure 1: Built-in Datatype Hierarchy
The built-in primitive and derived numerical XML Schema types are listed below together with their recommended typedef declarations. Note that the SOAP encoding schemas for primitive types are derived from the built-in XML Schema types, so SOAP_ENC__ can be used as a namespace prefix instead of xsd__.
xsd:anyURI
Represents a Uniform Resource Identifier Reference (URI). Each URI scheme imposes specialized syntax rules for URIs in that scheme, including restrictions on the syntax of allowed fragment identifiers. It is recommended to use strings to store xsd:anyURI XML Schema types. The recommended type declaration is:

typedef char *xsd__anyURI;

xsd:base64Binary
Represents Base64-encoded arbitrary binary data. For using the xsd:base64Binary XSD Schema type, the use of the base64Binary representation of a dynamic array is strongly recommended, see Section 10.12. However, the type can also be declared as a string and the encoding will be string-based:

typedef char *xsd__base64Binary;

With this approach, it is solely the responsibility of the application to make sure the string content is according to the Base64 Content-Transfer-Encoding defined in Section 6.8 of RFC 2045.
xsd:boolean
For declaring an xsd:boolean XSD Schema type, the use of a bool is strongly recommended. If a pure C compiler is used that does not support the bool type, see Section 10.4.5. The corresponding type declaration is:

typedef bool xsd__boolean;

Type xsd__boolean declares a Boolean (0 or 1), which is encoded as

<xsd:boolean xsi:type="xsd:boolean">...</xsd:boolean>

xsd:byte
Represents a byte (-128...127). The corresponding type declaration is:

typedef char xsd__byte;

Type xsd__byte declares a byte which is encoded as

<xsd:byte xsi:type="xsd:byte">...</xsd:byte>

xsd:dateTime
Represents a date and time. The lexical representation is according to the ISO 8601 extended format CCYY-MM-DDThh:mm:ss where "CC" represents the century, "YY" the year, "MM" the month and "DD" the day, preceded by an optional leading "-" sign to indicate a negative number. If the sign is omitted, "+" is assumed. The letter "T" is the date/time separator and "hh", "mm", "ss" represent hour, minute and second respectively. It is recommended to use the time_t type to store xsd:dateTime XSD Schema types and the type declaration is:

typedef time_t xsd__dateTime;

However, note that calendar times before the year 1902 or after the year 2037 cannot be represented. Upon receiving a date outside this range, the time_t value will be set to -1.
Strings (char*) can be used to store xsd:dateTime XSD Schema types. The type declaration is:

typedef char *xsd__dateTime;

In this case, it is up to the application to read and set the dateTime representation.
xsd:date
Represents a date. The lexical representation for date is the reduced (right truncated) lexical representation for dateTime: CCYY-MM-DD. It is recommended to use strings (char*) to store xsd:date XSD Schema types. The type declaration is:

typedef char *xsd__date;

xsd:decimal
Represents arbitrary precision decimal numbers. It is recommended to use the double type to store xsd:decimal XSD Schema types and the type declaration is:

typedef double xsd__decimal;

Type xsd__decimal declares a double floating point number which is encoded as

<xsd:double xsi:type="xsd:decimal">...</xsd:double>

xsd:double
Corresponds to the IEEE double-precision 64-bit floating point type. The type declaration is:

typedef double xsd__double;

Type xsd__double declares a double floating point number which is encoded as

<xsd:double xsi:type="xsd:double">...</xsd:double>

xsd:duration
Represents a duration of time. The lexical representation for duration is the ISO 8601 extended format PnYn MnDTnH nMnS, where nY represents the number of years, nM the number of months, nD the number of days, T is the date/time separator, nH the number of hours, nM the number of minutes and nS the number of seconds. The number of seconds can include decimal digits to arbitrary precision. It is recommended to use strings (char*) to store xsd:duration XSD Schema types. The type declaration is:

typedef char *xsd__duration;

xsd:float
Corresponds to the IEEE single-precision 32-bit floating point type. The type declaration is:

typedef float xsd__float;

Type xsd__float declares a floating point number which is encoded as

<xsd:float xsi:type="xsd:float">...</xsd:float>

xsd:hexBinary
Represents arbitrary hex-encoded binary data. It has a lexical representation where each binary octet is encoded as a character tuple, consisting of two hexadecimal digits ([0-9a-fA-F]) representing the octet code. For example, "0FB7" is a hex encoding for the 16-bit integer 4023 (whose binary representation is 111110110111. For using the xsd:hexBinary XSD Schema type, the use of the hexBinary representation of a dynamic array is strongly recommended, see Section 10.13. However, the type can also be declared as a string and the encoding will be string-based:

typedef char *xsd__hexBinary;

With this approach, it is solely the responsibility of the application to make sure the string content consists of a sequence of octets.
xsd:int
Corresponds to a 32-bit integer in the range -2147483648 to 2147483647. If the C++ compiler supports 32-bit int types, the type declaration can use the int type:

typedef int xsd__int;

Otherwise, the C++ compiler supports 16-bit int types and the type declaration should use the long type:

typedef long xsd__int;

Type xsd__int declares a 32-bit integer which is encoded as

<xsd:int xsi:type="xsd:int">...</xsd:int>

xsd:integer
Corresponds to an unbounded integer. Since C++ does not support unbounded integers as a standard feature, the recommended type declaration is:

typedef long long xsd__integer;

Type xsd__integer declares a 64-bit integer which is encoded as an unbounded xsd:integer:

<xsd:integer xsi:type="xsd:integer">...</xsd:integer>

Another possibility is to use strings to represent unbounded integers and do the translation in code.
xsd:long
Corresponds to a 64-bit integer in the range -9223372036854775808 to 9223372036854775807. The type declaration is:

typedef long long xsd__long;

Or in Visual C++:

typedef LONG64 xsd__long;

Type xsd__long declares a 64-bit integer which is encoded as

<xsd:long xsi:type="xsd:long">...</xsd:long>

xsd:negativeInteger
Corresponds to a negative unbounded integer ( < 0). Since C++ does not support unbounded integers as a standard feature, the recommended type declaration is:

typedef long long xsd__negativeInteger;

Type xsd__negativeInteger declares a 64-bit integer which is encoded as a xsd:negativeInteger:

<xsd:negativeInteger xsi:type="xsd:negativeInteger">...</xsd:negativeInteger>

Another possibility is to use strings to represent unbounded integers and do the translation in code.
xsd:nonNegativeInteger
Corresponds to a non-negative unbounded integer ( > 0). Since C++ does not support unbounded integers as a standard feature, the recommended type declaration is:

typedef unsigned long long xsd__nonNegativeInteger;

Type xsd__nonNegativeInteger declares a 64-bit unsigned integer which is encoded as a non-negative unbounded xsd:nonNegativeInteger:

<xsd:nonNegativeInteger xsi:type="xsd:nonNegativeInteger">...</xsd:nonNegativeInteger>

Another possibility is to use strings to represent unbounded integers and do the translation in code.
xsd:nonPositiveInteger
Corresponds to a non-positive unbounded integer ( £ 0). Since C++ does not support unbounded integers as a standard feature, the recommended type declaration is:

typedef long long xsd__nonPositiveInteger;

Type xsd__nonPositiveInteger declares a 64-bit integer which is encoded as a xsd:nonPositiveInteger:

<xsd:nonPositiveInteger xsi:type="xsd:nonPositiveInteger">...</xsd:nonPositiveInteger>

Another possibility is to use strings to represent unbounded integers and do the translation in code.
xsd:normalizedString
Represents normalized character strings. Normalized character strings do not contain the carriage return (#xD), line feed (#xA) nor tab (#x9) characters. It is recommended to use strings to store xsd:normalizeString XSD Schema types. The type declaration is:

typedef char *xsd__normalizedString;

Type xsd__normalizedString declares a string type which is encoded as

<xsd:normalizedString xsi:type="xsd:normalizedString">...</xsd:normalizedString>

It is solely the responsibility of the application to make sure the strings do not contain carriage return (#xD), line feed (#xA) and tab (#x9) characters.
xsd:positiveInteger
Corresponds to a positive unbounded integer ( ³ 0). Since C++ does not support unbounded integers as a standard feature, the recommended type declaration is:

typedef unsigned long long xsd__positiveInteger;

Type xsd__positiveInteger declares a 64-bit unsigned integer which is encoded as a xsd:positiveInteger:

<xsd:positiveInteger xsi:type="xsd:positiveInteger">...</xsd:positiveInteger>

Another possibility is to use strings to represent unbounded integers and do the translation in code.
xsd:short
Corresponds to a 16-bit integer in the range -32768 to 32767. The type declaration is:

typedef short xsd__short;

Type xsd__short declares a short 16-bit integer which is encoded as

<xsd:short xsi:type="xsd:short">...</xsd:short>

xsd:string
Represents character strings. The type declaration is:

typedef char *xsd__string;

Type xsd__string declares a string type which is encoded as

<xsd:string xsi:type="xsd:string">...</xsd:string>

The type declaration for wide character strings is:

typedef wchar_t *xsd__string;

Both type of strings can be used at the same time, but requires one typedef name to be changed by appending an underscore which is invisible in XML. For example:

typedef wchar_t *xsd__string_;

xsd:time
Represents a time. The lexical representation for time is the left truncated lexical representation for dateTime: hh:mm:ss.sss with optional following time zone indicator. It is recommended to use strings (char*) to store xsd:time XSD Schema types. The type declaration is:

typedef char *xsd__time;

xsd:token
Represents tokenized strings. Tokens are strings that do not contain the line feed (#xA) nor tab (#x9) characters, that have no leading or trailing spaces (#x20) and that have no internal sequences of two or more spaces. It is recommended to use strings to store xsd:token XSD Schema types. The type declaration is:

typedef char *xsd__token;

Type xsd__token declares a string type which is encoded as

<xsd:token xsi:type="xsd:token">...</xsd:token>

It is solely the responsibility of the application to make sure the strings do not contain the line feed (#xA) nor tab (#x9) characters, that have no leading or trailing spaces (#x20) and that have no internal sequences of two or more spaces.
xsd:unsignedByte
Corresponds to an 8-bit unsigned integer in the range 0 to 255. The type declaration is:

typedef unsigned char xsd__unsignedByte;

Type xsd__unsignedByte declares a unsigned 8-bit integer which is encoded as

<xsd:unsignedByte xsi:type="xsd:unsignedByte">...</xsd:unsignedByte>

xsd:unsignedInt
Corresponds to a 32-bit unsigned integer in the range 0 to 4294967295. If the C++ compiler supports 32-bit int types, the type declaration can use the int type:

typedef unsigned int xsd__unsignedInt;

Otherwise, the C++ compiler supports 16-bit int types and the type declaration should use the long type:

typedef unsigned long xsd__unsignedInt;

Type xsd__unsignedInt declares an unsigned 32-bit integer which is encoded as

<xsd:unsignedInt xsi:type="xsd:unsignedInt">...</xsd:unsignedInt>

xsd:unsignedLong
Corresponds to a 64-bit unsigned integer in the range 0 to 18446744073709551615. The type declaration is:

typedef unsigned long long xsd__unsignedLong;

Or in Visual C++:

typedef ULONG64 xsd__unsignedLong;

Type xsd__unsignedLong declares an unsigned 64-bit integer which is encoded as

<xsd:unsignedLong xsi:type="xsd:unsignedLong">...</xsd:unsignedLong>

xsd:unsignedShort
Corresponds to a 16-bit unsigned integer in the range 0 to 65535. The type declaration is:

typedef unsigned short xsd__unsignedShort;

Type xsd__unsginedShort declares an unsigned short 16-bit integer which is encoded as

<xsd:unsignedShort xsi:type="xsd:unsignedShort">...</xsd:unsignedShort>

Other XSD Schema types such as gYearMonth, gYear, gMonthDay, gDay, xsd:gMonth, QName, NOTATION, etc., can be encoded similarly using a typedef declaration.

10.3.1  How to Use Multiple C/C++ Types for a Single Primitive XSD Type

Trailing underscores (see Section 9.3) can be used in the type name in a typedef to enable the declaration of multiple storage formats for a single XML Schema type. For example, one part of a C/C++ application's data structure may use plain strings while another part may use wide character strings. To enable this simultaneous use, declare:

typedef char *xsd__string;
typedef wchar_t *xsd__string_;

Now, the xsd__string and xsd__string_ types will both be encoded and decoded as XML string types and the use of trailing underscores allows multiple declarations for a single XML Schema type.

10.3.2  How to use Wrapper Classes to Specify Polymorphic Primitive Types

SOAP 1.1 supports polymorphic types, because XSD Schema types form a hierarchy. The root of the hierarchy is called xsd:anyType (xsd:ur-type in the older 1999 schema). So, for example, an array of xsd:anyType in SOAP may actually contain any mix of element types that are the derived types of the root type. The use of polymorphic types is indicated by the WSDL and schema descriptions of a Web service and can therefore be predicted/expected for each particular case.
On the one hand, the typedef construct provides a convenient way to associate C/C++ types with XML Schema types and makes it easy to incorporate these types in a (legacy) C/C++ application. However, on the other hand the typedef declarations cannot be used to support polymorphic XML Schema types. Most SOAP clients and services do not use polymorphic types. In case they do, the primitive polymorphic types can be declared as a hierarchy of C++ classes that can be used simultaneously with the typedef declarations.
The general form of a primitive type declaration that is derived from a super type is:

class xsd__type_name: [public xsd__super_type_name]
{ public: Type __item;
   [public:] [private] [protected:]
   method1;
   method2;
   ...
};

where Type is a primitive C type. The __item field MUST be the first field in this wrapper class.
For example, the XML Schema type hierarchy can be copied to C++ with the following declarations:

class xsd__anyType { };
class xsd__anySimpleType: public xsd__anyType { };
typedef char *xsd__anyURI;
class xsd__anyURI_: public xsd__anySimpleType { public: xsd__anyURI __item; };
typedef bool xsd__boolean;
class xsd__boolean_: public xsd__anySimpleType { public: xsd__boolean __item; };
typedef char *xsd__date;
class xsd__date_: public xsd__anySimpleType { public: xsd__date __item; };
typedef time_t xsd__dateTime;
class xsd__dateTime_: public xsd__anySimpleType { public: xsd__dateTime __item; };
typedef double xsd__double;
class xsd__double_: public xsd__anySimpleType { public: xsd__double __item; };
typedef char *xsd__duration;
class xsd__duration_: public xsd__anySimpleType { public: xsd__duration __item; };
typedef float xsd__float;
class xsd__float_: public xsd__anySimpleType { public: xsd__float __item; };
typedef char *xsd__time;
class xsd__time_: public xsd__anySimpleType { public: xsd__time __item; };
typedef char *xsd__decimal;
class xsd__decimal_: public xsd__anySimpleType { public: xsd__decimal __item; };
typedef char *xsd__integer;
class xsd__integer_: public xsd__decimal_ { public: xsd__integer __item; };
typedef LONG64 xsd__long;
class xsd__long_: public xsd__integer_ { public: xsd__long __item; };
typedef long xsd__int;
class xsd__int_: public xsd__long_ { public: xsd__int __item; };
typedef short xsd__short;
class xsd__short_: public xsd__int_ { public: xsd__short __item; };
typedef char xsd__byte;
class xsd__byte_: public xsd__short_ { public: xsd__byte __item; };
typedef char *xsd__nonPositiveInteger;
class xsd__nonPositiveInteger_: public xsd__integer_ { public: xsd__nonPositiveInteger __item; };
typedef char *xsd__negativeInteger;
class xsd__negativeInteger_: public xsd__nonPositiveInteger_ { public: xsd__negativeInteger __item; };
typedef char *xsd__nonNegativeInteger;
class xsd__nonNegativeInteger_: public xsd__integer_ { public: xsd__nonNegativeInteger __item; };
typedef char *xsd__positiveInteger;
class xsd__positiveInteger_: public xsd__nonNegativeInteger_ { public: xsd__positiveInteger __item; };
typedef ULONG64 xsd__unsignedLong;
class xsd__unsignedLong_: public xsd__nonNegativeInteger_ { public: xsd__unsignedLong __item; };
typedef unsigned long xsd__unsignedInt;
class xsd__unsignedInt_: public xsd__unsginedLong_ { public: xsd__unsignedInt __item; };
typedef unsigned short xsd__unsignedShort;
class xsd__unsignedShort_: public xsd__unsignedInt_ { public: xsd__unsignedShort __item; };
typedef unsigned char xsd__unsignedByte;
class xsd__unsignedByte_: public xsd__unsignedShort_ { public: xsd__unsignedByte __item; };
typedef char *xsd__string;
class xsd__string_: public xsd__anySimpleType { public: xsd__string __item; };
typedef char *xsd__normalizedString;
class xsd__normalizedString_: public xsd__string_ { public: xsd__normalizedString __item; };
typedef char *xsd__token;
class xsd__token_: public xsd__normalizedString_ { public: xsd__token __item; };

Note the use of the trailing underscores for the class names to distinguish the typedef type names from the class names. Only the most frequently used built-in schema types are shown. It is also allowed to include the xsd:base64Binary and xsd:hexBinary types in the hierarchy:

class xsd__base64Binary: public xsd__anySimpleType { public: unsigned char *__ptr; int __size; };
class xsd__hexBinary: public xsd__anySimpleType { public: unsigned char *__ptr; int __size; };

See Sections 10.12 and 10.13.
Methods are allowed to be added to the classes above, such as constructors and getter/setter methods, see Section 10.6.4.
Wrapper structs are supported as well, similar to wrapper classes. But they cannot be used to implement polymorphism. Rather, the wrapper structs facilitate the use of XML attributes with a primitive typed object, see 10.6.7.

10.3.3  XSD Schema Type Decoding Rules

The decoding rules for the primitive C and C++ data types is given in the table below:

Type Allows Decoding of Precision Lost?
bool [xsd:]boolean no
char* (C string) any type, see 10.3.5 no
wchar_t * (wide string) any type, see 10.3.5 no
double [xsd:]double no
[xsd:]float no
[xsd:]long no
[xsd:]int no
[xsd:]short no
[xsd:]byte no
[xsd:]unsignedLong no
[xsd:]unsignedInt no
[xsd:]unsignedShort no
[xsd:]unsignedByte no
[xsd:]decimal possibly
[xsd:]integer possibly
[xsd:]positiveInteger possibly
[xsd:]negativeInteger possibly
[xsd:]nonPositiveInteger possibly
[xsd:]nonNegativeInteger possibly
float [xsd:]float no
[xsd:]long no
[xsd:]int no
[xsd:]short no
[xsd:]byte no
[xsd:]unsignedLong no
[xsd:]unsignedInt no
[xsd:]unsignedShort no
[xsd:]unsignedByte no
[xsd:]decimal possibly
[xsd:]integer possibly
[xsd:]positiveInteger possibly
[xsd:]negativeInteger possibly
[xsd:]nonPositiveInteger possibly
[xsd:]nonNegativeInteger possibly
long long [xsd:]long no
[xsd:]int no
[xsd:]short no
[xsd:]byte no
[xsd:]unsignedLong possibly
[xsd:]unsignedInt no
[xsd:]unsignedShort no
[xsd:]unsignedByte no
[xsd:]integer possibly
[xsd:]positiveInteger possibly
[xsd:]negativeInteger possibly
[xsd:]nonPositiveInteger possibly
[xsd:]nonNegativeInteger possibly



Type Allows Decoding of Precision Lost?
long [xsd:]long possibly, if long is 32 bit
[xsd:]int no
[xsd:]short no
[xsd:]byte no
[xsd:]unsignedLong possibly
[xsd:]unsignedInt no
[xsd:]unsignedShort no
[xsd:]unsignedByte no
int [xsd:]int no
[xsd:]short no
[xsd:]byte no
[xsd:]unsignedInt possibly
[xsd:]unsignedShort no
[xsd:]unsignedByte no
short [xsd:]short no
[xsd:]byte no
[xsd:]unsignedShort no
[xsd:]unsignedByte no
char [xsd:]byte no
[xsd:]unsignedByte possibly
unsigned long long [xsd:]unsignedLong no
[xsd:]unsignedInt no
[xsd:]unsignedShort no
[xsd:]unsignedByte no
[xsd:]positiveInteger possibly
[xsd:]nonNegativeInteger possibly
unsigned long [xsd:]unsignedLong possibly, if long is 32 bit
[xsd:]unsignedInt no
[xsd:]unsignedShort no
[xsd:]unsignedByte no
unsigned int [xsd:]unsignedInt no
[xsd:]unsignedShort no
[xsd:]unsignedByte no
unsigned short [xsd:]unsignedShort no
[xsd:]unsignedByte no
unsigned char [xsd:]unsignedByte no
time_t [xsd:]dateTime no(?)

Due to limitations in representation of certain primitive C++ types, a possible loss of accuracy may occur with the decoding of certain XSD Schema types as is indicated in the table. The table does not indicate the possible loss of precision of floating point values due to the textual representation of floating point values in SOAP.
All explicitly declared XSD Schema encoded primitive types adhere to the same decoding rules. For example, the following declaration:

typedef unsigned long long xsd__nonNegativeInteger;

enables the encoding and decoding of xsd:nonNegativeInteger XSD Schema types (although decoding takes place with a possible loss of precision). The declaration also allows decoding of xsd:positiveInteger XSD Schema types, because of the storage as a unsigned long long data type.

10.3.4  Multi-Reference Strings

If more than one char pointer points to the same string, the string is encoded as a multi-reference value. Consider for example

char *s = "hello", *t = s;

The s and t variables are assigned the same string, and when serialized, t refers to the content of s:

<string id="123" xsi:type="string">hello</string>
...
<string href="#123"/>

The example assumed that s and t are encoded as independent elements.
Note: the use of typedef to declare a string type such as xsd__string will not affect the multi-reference string encoding. However, strings declared with different typedefs will never be considered multi-reference even when they point to the same string. For example

typedef char *xsd__string;
typedef char *xsd__anyURI;
xsd__anyURI *s = "http://www.myservice.com";
xsd__string *t = s;

The variables s and t point to the same string, but since they are considered different types their content will not be shared in the SOAP payload through a multi-referenced string.

10.3.5  "Smart String" Mixed-Content Decoding

The implementation of string decoding in gSOAP allows for mixed content decoding. If the SOAP payload contains a complex data type in place of a string, the complex data type is decoded in the string as plain XML text.
For example, suppose the getInfo remote method returns some detailed information. The remote method is declared as:

// Contents of header file "getInfo.h":
getInfo(char *detail);

The proxy of the remote method is used by a client to request a piece of information and the service responds with:

HTTP/1.1 200 OK
Content-Type: text/xml
Content-Length: nnn

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
   xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
<SOAP-ENV:Body>
<getInfoResponse>
<detail>
<picture>Mona Lisa by <i>Leonardo da Vinci</i></picture>
</detail>
</getInfoResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

As a result of the mixed content decoding, the detail string contains "<picture>Mona Lisa by <i>Leonardo da Vinci</i></picture>".

10.3.6  STL Strings

gSOAP supports STL strings std::string and std::wstring. For example:

typedef std::string xsd__string;
class ns__myClass
{ public:
   xsd__string s; // serialized with xsi:type="xsd:string"
   std::string t; // serialized without xsi:type
...
};

Caution: Please avoid mixing std::string and C strings (char*) in the header file when using SOAP 1.1 encoding. The problem is that multi-referenced strings in SOAP encoded messages cannot be assigned simultaneously to a std::string and a char* string.

10.3.7  Changing the Encoding Precision of float and double Types

The double encoding format is by default set to "%.18G" (see a manual on printf text formatting in C), i.e. at most 18 digits of precision to limit a loss in accuracy. The float encoding format is by default "%.9G", i.e. at most 9 digits of precision.
The encoding format of a double type can be set by assigning a format string to soap.double_format, where soap is a variable that contains the current runtime environment. For example:

struct soap soap;
soap_init(&soap); // sets double_format = "%.18G"
soap.double_format = "%e"; // redefine

which causes all doubles to be encoded in scientific notation. Likewise, the encoding format of a float type can be set by assigning a format string to the static soap_float_format string variable. For example:

struct soap soap;
soap_init(&soap); // sets float_format = "%.9G"
soap.float_format = "%.4f"; // redefine

which causes all floats to be encoded with four digits precision.
Caution: The format strings are not automatically reset before or after SOAP communications. An error in the format string may result in the incorrect encoding of floating point values.

10.3.8  INF, -INF, and NaN Values of float and double Types

The gSOAP runtime stdsoap2.cpp and header file stdsoap2.h support the marshalling of IEEE INF, -INF, and NaN representations. Under certain circumstances this may break if the hardware and/or C/C++ compiler does not support these representations. To remove the representations, remove the inclusion of the < math.h > header file from the stdsoap2.h file. You can control the representations as well, which are defined by the macros:

#define FLT_NAN
#define FLT_PINFTY
#define FLT_NINFTY
#define DBL_NAN
#define DBL_PINFTY
#define DBL_NINFTY

10.4  Enumeration Serialization

Enumerations are generally useful for the declaration of named integer-valued constants, also called enumeration constants.

10.4.1  Serialization of Symbolic Enumeration Constants

The gSOAP stub and skeleton compiler encodes the constants of enumeration-typed variables in symbolic form using the names of the constants when possible to comply to SOAP's enumeration encoding style. Consider for example the following enumeration of weekdays:

enum weekday {Mon, Tue, Wed, Thu, Fri, Sat, Sun};

The enumeration-constant Mon, for example, is encoded as

<weekday xsi:type="weekday">Mon</weekday>

The value of the xsi:type attribute is the enumeration-type identifier's name. If the element is independent as in the example above, the element name is the enumeration-type identifier's name.
The encoding of complex types such as enumerations requires a reference to an XML Schema through the use of a namespace prefix. The namespace prefix can be specified as part of the enumeration-type identifier's name, with the usual namespace prefix conventions for identifiers. This can be used to explicitly specify the encoding style. For example:

enum ns1__weekday {Mon, Tue, Wed, Thu, Fri, Sat, Sun};

The enumeration-constant Sat, for example, is encoded as:

<ns1:weekday xsi:type="ns1:weekday">Sat</ns1:weekday>

The corresponding XML Schema for this enumeration data type would be:

<xsd:element name="weekday" type="tns:weekday"/>
<xsd:simpleType name="weekday">
   <xsd:restriction base="xsd:string">
      <xsd:enumeration value="Mon"/>
      <xsd:enumeration value="Tue"/>
      <xsd:enumeration value="Wed"/>
      <xsd:enumeration value="Thu"/>
      <xsd:enumeration value="Fri"/>
      <xsd:enumeration value="Sat"/>
      <xsd:enumeration value="Sun"/>
   </xsd:restriction>
</xsd:simpleType>

10.4.2  Encoding of Enumeration Constants

If the value of an enumeration-typed variable has no corresponding named constant, the value is encoded as a signed integer literal. For example, the following declaration of a workday enumeration type lacks named constants for Saturday and Sunday:

enum ns1__workday {Mon, Tue, Wed, Thu, Fri};

If the constant 5 (Saturday) or 6 (Sunday) is assigned to a variable of the workday enumeration type, the variable will be encoded with the integer literals 5 and 6, respectively. For example:

<ns1:workday xsi:type="ns1:workday">5</ns1:workday>

Since this is legal in C++ and SOAP allows enumeration constants to be integer literals, this method ensures that non-symbolic enumeration constants are correctly communicated to another party if the other party accepts literal enumeration constants (as with the gSOAP stub and skeleton compiler).
Both symbolic and literal enumeration constants can be decoded.
To enforce the literal enumeration constant encoding and to get the literal constants in the WSDL file, use the following trick:

enum ns1__nums { _1 = 1, _2 = 2, _3 = 3 };

The difference with an enumeration type without a list of values and the enumeration type above is that the enumeration constants will appear in the WSDL service description.

10.4.3  Initialized Enumeration Constants

The gSOAP compiler supports the initialization of enumeration constants, as in:

enum ns1__relation {LESS = -1, EQUAL = 0, GREATER = 1};

The symbolic names LESS, EQUAL, and GREATER will appear in the SOAP payload for the encoding of the ns1__relation enumeration values -1, 0, and 1, respectively.

10.4.4  How to "Reuse" Symbolic Enumeration Constants

A well-known deficiency of C and C++ enumeration types is the lack of support for the reuse of symbolic names by multiple enumerations. That is, the names of all the symbolic constants defined by an enumeration cannot be reused by another enumeration. To force encoding of the same symbolic name by different enumerations, the identifier of the symbolic name can end in an underscore (_) or any number of underscores to distinguish it from other symbolic names in C++. This guarantees that the SOAP encoding will use the same name, while the symbolic names can be distinguished in C++. Effectively, the underscores are removed from a symbolic name prior to encoding.
Consider for example:

enum ns1__workday {Mon, Tue, Wed, Thu, Fri};
enum ns1__weekday {Mon_, Tue_, Wed_, Thu_, Fri_, Sat_, Sun_};

which will result in the encoding of the constants of enum ns1__weekday without the underscore, for example as Mon.
Caution: The following declaration:

enum ns1__workday {Mon, Tue, Wed, Thu, Fri};
enum ns1__weekday {Sat = 5, Sun = 6};

will not properly encode the weekday enumeration, because it lacks the named constants for workday in its enumeration list.

10.4.5  Boolean Enumeration Serialization for C

When developing a C Web service application, the C++ bool type should not be used since it is not usually supported by the C compiler. Instead, an enumeration type should be used to serialize true/false values as xsd:boolean Schema type enumeration values. The xsd:boolean XML Schema type is defined as:

enum xsd__boolean {false_, true_};

The value false_, for example, is encoded as:

<xsd:boolean xsi:type="xsd:boolean">false</xsd:boolean>

Peculiar of the SOAP boolean type encoding is that it only defines the values 0 and 1, while the built-in XML Schema boolean type also defines the false and true symbolic constants as valid values. The following example declaration of an enumeration type lacks named constants altogether to force encoding of the enumeration values as literal constants:

enum SOAP_ENC__boolean {};

The value 0, for example, is encoded with an integer literal:

<SOAP-ENC:boolean xsi:type="SOAP-ENC:boolean">0<SOAP-ENC:boolean>

10.4.6  Bitmask Enumeration Serialization

A bitmask is an enumeration of flags such as declared with C#'s [Flags] enum annotation. gSOAP supports bitmask encoding and decoding for interoperability. However, bitmask types are not standardized with SOAP RPC.
A special syntactic convention is used in the header file input to the gSOAP compiler to indicate the use of bitmasks with an asterisk:

enum * name { enum-constant, enum-constant, ... };

The gSOAP compiler will encode the enumeration constants as flags, i.e. as a series of powers of 2 starting with 1. The enumeration constants can be or-ed to form a bitvector (bitmask) which is encoded and decoded as a list of symbolic values in SOAP. For example:

enum * ns__machineStatus { ON, BELT, VALVE, HATCH};
int ns__getMachineStatus(char *name, char *enum ns__machineStatus result);

Note that the use of the enum does not require the asterisk, only the definition. The gSOAP compiler generates the enumeration:

enum ns__machineStatus { ON=1, BELT=2, VALVE=4, HATCH=8};

A remote method implementation in a Web service can return:

int ns__getMachineStatus(struct soap *soap, char *name, enum ns__machineStatus result)
{ ...
   *result = BELT - HATCH;
   return SOAP_OK;
}

10.5  Struct Serialization

A struct data type is encoded as an XML Schema complexType (SOAP-encoded compound data type) such that the struct name forms the data type's element name and schema type and the fields of the struct are the data type's accessors. This encoding is identical to the class instance encoding without inheritance and method declarations, see Section 10.6 for further details. However, the encoding and decoding of structs is more efficient compared to class instances due to the lack of inheritance and the requirement by the serialization routines to check inheritance properties at run time.
Certain type of fields of a struct can be (de)serialized as XML attributes. See 10.6.7 for more details.

10.6  Class Instance Serialization

A class instance is serialized as an XML Schema complexType (SOAP-encoded compound data type) such that the class name forms the data type's element name and schema type and the data member fields are the data type's accessors. Only the data member fields are encoded in the SOAP payload. Class methods are not encoded.
The general form of a class declaration is:

class [namespace_prefix__]class_name1 [:[public:] [private:] [protected:] [namespace_prefix__]class_name2]
{
   [public:] [private:] [protected:]
   field1;
   field2;
   ...
   [public:] [private:] [protected:]
   method1;
   method2;
   ...
};

where
namespace_prefix__
is the optional namespace prefix of the compound data type (see identifier translation rules 9.3)
class_name1
is the element name of the compound data type (see identifier translation rules 9.3).
class_name2
is an optional base class.
field
is a field declaration (data member). A field MAY be declared static and const and MAY be initialized.
method
is a method declaration. A method MAY be declared virtual, but abstract methods are not allowed. The method parameter declarations are REQUIRED to have parameter identifier names.
[public:] [private:] [protected:]
are OPTIONAL. Only members with public acces permission can be serialized.
A class name is REQUIRED to be unique and cannot have the same name as a struct, enum, or remote method name specified in the header file input to the gSOAP compiler. The reason is that remote method requests are encoded similarly to class instances in SOAP and they are in principle undistinguishable (the method parameters are encoded just as the fields of a class).
Only single inheritance is supported by the gSOAP compiler. Multiple inheritance is not supported, because of the limitations of the SOAP protocol.
If a constructor method is present, there MUST also be a constructor declaration with empty parameter list.
Classes should be declared "volatile" if you don't want gSOAP to add serialization methods to these classes, see Section 18.4 for more details.
Class templates are not supported by the gSOAP compiler, but you can use STL containers, see Section 10.11.8. You can also define your own containers similar to STL containers.
Certain fields of a class can be (de)serialized as XML attributes. See 10.6.7 for more details.
Arrays may be embedded within a class (and struct) using a pointer field and size information, see Section 10.11.7. This defines what is sometimes referred to in SOAP as "generics".
Void pointers may be used in a class (or struct), but you have to add a type field so the gSOAP runtime can determine the type of object pointed to, see Section 10.9.
A class instance is encoded as:

<[namespace-prefix:]class-name xsi:type="[namespace-prefix:]class-name">
<basefield-name1 xsi:type="...">...</basefield-name1>
<basefield-name2 xsi:type="...">...</basefield-name2>
...
<field-name1 xsi:type="...">...</field-name1>
<field-name2 xsi:type="...">...</field-name2>
...
</[namespace-prefix:]class-name>

where the field-name accessors have element-name representations of the class fields and the basefield-name accessors have element-name representations of the base class fields. (The optional parts resulting from the specification are shown enclosed in [].)
The decoding of a class instance allows any ordering of the accessors in the SOAP payload. However, if a base class field name is identical to a derived class field name because the field is overloaded, the base class field name MUST precede the derived class field name in the SOAP payload for decoding. gSOAP guarantees this, but interoperability with other SOAP implementations is cannot be guaranteed.

10.6.1  Example

The following example declares a base class ns__Object and a derived class ns__Shape:

// Contents of file "shape.h":
class ns__Object
{
   public:
   char *name;
};
class ns__Shape : public ns__Object
{
   public:
   int sides;
   enum ns__Color {Red, Green, Blue} color;
   ns__Shape();
   ns__Shape(int sides, enum ns__Green color);
   ~ns__Shape();
};

The implementation of the methods of class ns__Shape must not be part of the header file and need to be defined elsewhere.
An instance of class ns__Shape with name Triangle, 3 sides, and color Green is encoded as:

<ns:Shape xsi:type="ns:Shape">
<name xsi:type="string">Triangle</name>
<sides xsi:type="int">3</sides>
<color xsi:type="ns:Color">Green</color>
</ns:shape>

The namespace URI of the namespace prefix ns must be defined by a namespace mapping table, see Section 9.4.

10.6.2  Initialized static const Fields

A data member field of a class declared as static const is initialized with a constant value at compile time. This field is encoded in the serialization process, but is not decoded in the deserialization process. For example:

// Contents of file "triangle.h":
class ns__Triangle : public ns__Object
{
   public:
   int size;
   static const int sides = 3;
};

An instance of class ns__Triangle is encoded in SOAP as:

<ns:Triangle xsi:type="ns:Triangle">
<name xsi:type="string">Triangle</name>
<size xsi:type="int">15</size>
<sides xsi:type="int">3>/sides>
</ns:Triangle>

Decoding will ignore the sides field's value.
Caution: The current gSOAP implementation does not support encoding static const fields, due to C++ compiler compatibility differences. This feature may be provided the future.

10.6.3  Class Methods

A class declaration in the header file input to the gSOAP compiler MAY include method declarations. The method implementations MUST NOT be part of the header file but are required to be defined in another C++ source that is externally linked with the application. This convention is also used for the constructors and destructors of the class.
Dynamic binding is supported, so a method MAY be declared virtual.

10.6.4  Getter and Setter Methods

Setter and getter methods are invoked at run time upon serialization and deserialization of class instances, respectively. The use of setter and getter methods adds more flexibility to the serialization and deserialization process.
A setter method is called in the serialization phase from the virtual soap_serialization method generated by the gSOAP compiler. You can use setter methods to process a class instance just before it is serialized. A setter method can be used to convert application data, such as translating transient application data into serializable data, for example. You can also use setter methods to retrieve dynamic content and use it to update a class instance right before serialization. Remember setters as ßet to serialize" operations.
Getter methods are invoked after deserialization of the instance. You can use them to adjust the contents of class instances after all their members have been deserialized. Getters can be used to convert deserialized members into transient members and even invoke methods to process the deserialized data on the fly.
Getter and setter methods have the following signature:

[virtual] int get(struct soap *soap) [const];
[virtual] int set(struct soap *soap);

The active soap struct will be passed to the get and set methods. The methods should return SOAP_OK when successful. A setter method should prepare the contents of the class instance for serialization. A getter method should process the instance after deserialization.
Here is an example of a base64 binary class:

class xsd__base64Binary
{ public:
   unsignedchar *__ptr;
   int__size;
   int get(struct soap *soap);
   int set(struct soap *soap);
};

Suppose that the type and options members of the attachment should be set when the class is about to be serialized. This can be accomplished with the set method from the information provided by the __ptr to the data and the soap struct passed to the set method (you can pass data via the void*soap.user field).
The get method is invoked after the base64 data has been processed. You can use it for post-processing purposes.
Here is another example. It defines a primitive update type. The class is a wrapper for the time_t type, see Section 10.3.2. Therefore, elements of this type contain xsd:dateType data.

class update
{ public:
   time_t __item;
   int set(struct soap *soap);
};

The setter method assigns the current time:

int update::set(struct soap *soap)
{
   this->__item = time(NULL);
   return SOAP_OK;
}

Therefore, serialization results in the inclusion of a time stamp in XML.
Caution: a get method is invoked only when the XML element with its data was completely parsed. The method is not invoked when the element is an xsi:nil element or has an href attribute.
Caution: The soap_serialize method of a class calls the setter (when provided). However, the soap_serialize method is declared const while the setter should be allowed to modify the contents of the class instance. Therefore, the gSOAP-generated code recasts the instance and the const is removed when invoking the setter.

10.6.5  Streaming XML with Getter and Setter Methods

Getter methods enable streaming XML operations. A getter method is invoked when the object is deserialized and the rest of the SOAP/XML message has not been processed yet. For example, you can add a getter method to the SOAP Header class to implement header processing logic that is activated as soon as the SOAP Header is received. An example code is shown below:

class h__Authentication
{ public:
   char *id;
   int get(struct soap *soap);
};
class SOAP_ENV__Header
{ public:
   h__Authentication *h__authentication;
};

The Authentication SOAP Header field is instantiated and decoded. After decoding, the getter method is invoked, which can be used to check the id before the rest of the SOAP message is processed.

10.6.6  Polymorphism, Derived Classes, and Dynamic Binding

Interoperability between client and service applications developed with gSOAP is established even when clients and/or services use derived classes instead of the base classes used in the declaration of the remote method parameters. A client application MAY use pointers to instances of derived classes for the input parameters of a remote method. If the service was compiled with a declaration and implementation of the derived class, the remote method base class input parameters are demarshalled and a derived class instance is created instead of a base class instance. If the service did not include a declaration of the derived class, the derived class fields are ignored and a base class instance is created. Therefore, interoperability is guaranteed even when the client sends an instance of a derived classes and when a service returns an instance of a derived class.
The following example declares Base and Derived classes and a remote method that takes a pointer to a Base class instance and returns a Base class instance:

// Contents of file "derived.h"
class Base
{
   public:
   char *name;
   Base();
   virtual void print();
};
class Derived : public Base
{
   public:
   int num;
   Derived();
   virtual void print();
};
int method(Base *in, struct methodResponse { Base *out; } &result);

This header file specification is processed by the gSOAP compiler to produce the stub and skeleton routines which are used to implement a client and service. The pointer of the remote method is also allowed to point to Derived class instances and these instances will be marshalled as Derived class instances and send to a service, which is in accord to the usual semantics of parameter passing in C++ with dynamic binding.
The Base and Derived class method implementations are:

// Method implementations of the Base and Derived classes:
#include "soapH.h"
...
Base::Base()
{
   cout << "created a Base class instance" << endl;
}
Derived::Derived()
{
   cout << "created a Derived class instance" << endl;
}
Base::print()
{
   cout << "print(): Base class instance " << name << endl;
}
Derived::print()
{
   cout << "print(): Derived class instance " << name << " " << num << endl;
}

Below is an example CLIENT application that creates a Derived class instance that is passed as the input parameter of the remote method:

// CLIENT
#include "soapH.h"
int main()
{
   struct soap soap;
   soap_init(&soap);
   Derived obj1;
   Base *obj2;
   struct methodResponse r;
   obj1.name = "X";
   obj1.num = 3;
   soap_call_method(&soap, url, action, &obj1, r);
   r.obj2->print();
}
...

The following example SERVER1 application copies a class instance (Base or Derived class) from the input to the output parameter:

// SERVER1
#include "soapH.h"
int main()
{
   soap_serve(soap_new());
}
int method(struct soap *soap, Base *obj1, struct methodResponse &result)
{
   obj1->print();
   result.obj2 = obj1;
   return SOAP_OK;
}
...

The following messages are produced by the CLIENT and SERVER1 applications:

CLIENT: created a Derived class instance
SERVER1: created a Derived class instance
SERVER1: print(): Derived class instance X 3
CLIENT: created a Derived class instance
CLIENT: print(): Derived class instance X 3

Which indicates that the derived class kept its identity when it passed through SERVER1. Note that instances are created both by the CLIENT and SERVER1 by the demarshalling process.
Now suppose a service application is developed that only accepts Base class instances. The header file is:

// Contents of file "base.h":
class Base
{
   public:
   char *name;
   Base();
   virtual void print();
};
int method(Base *in, Base *out);

This header file specification is processed by the gSOAP stub and skeleton compiler to produce skeleton routine which is used to implement a service (so the client will still use the derived classes).
The method implementation of the Base class are:

// Method implementations of the Base class:
#include "soapH.h"
...
Base::Base()
{
   cout << "created a Base class instance" << endl;
}
Base::print()
{
   cout << "print(): Base class instance " << name << endl;
}

And the SERVER2 application is that uses the Base class is:

// SERVER2
#include "soapH.h"
int main()
{
   soap_serve(soap_new());
}
int method(struct soap *soap, Base *obj1, struct methodResponse &result)
{
   obj1->print();
   result.obj2 = obj1;
   return SOAP_OK;
}
...

Here are the messages produced by the CLIENT and SERVER2 applications:

CLIENT: created a Derived class instance
SERVER2: created a Base class instance
SERVER2: print(): Base class instance X
CLIENT: created a Base class instance
CLIENT: print(): Base class instance X

In this example, the object was passed as a Derived class instance to SERVER2. Since SERVER2 only implements the Base class, this object is converted to a Base class instance and send back to CLIENT.

10.6.7  XML Attributes

The SOAP RPC/LIT and SOAP DOC/LIT encoding styles support XML attributes in SOAP messages while SOAP RPC with "Section 5" encoding does not support XML attributes other than the SOAP and XSD specific attributes. SOAP RPC "Section 5" encoding has advantages for cross-language interoperability and data encodings such as graph serialization. However, RPC/LIT and DOC/LIT enables direct exchange of XML documents, which may include encoded application data structures. Language interoperability is compromised, because no mapping between XML and the typical language data types is defined. The meaning of the RPC/LIT and DOC/LIT XML content is Schema driven rather than application/language driven.
gSOAP supports XML attribute (de)serialization of members in structs and classes. Attributes are primitive XSD types, such as strings, enumerations, boolean, and numeric types. To declare an XML attribute in a struct/class, the qualifier @ is used with the type of the attribute. The type must be primitive type (including enumerations and strings), which can be declared with or without a typedef to associate a XSD type with the C/C+ type. For example

typedef char *xsd__string;
typedef bool *xsd__boolean;
enum ns__state { _0, _1, _2 };
struct ns__myStruct
{
   @xsd__string ns__type; // encode as XML attribute 'ns:type' of type 'xsd:string'
   @xsd__boolean ns__flag = false; // encode as XML attribute 'ns:flag' of type 'xsd:boolean'
   @enum ns__state ns__state = _2; // encode as XML attribute 'ns:state' of type 'ns:state'
   struct ns__myStruct *next;
};

The @ qualifier indicates XML attribute encoding for the ns__type, ns__flag, and ns__state fields. Note that the namespace prefix ns is used to distinguish these attributes from any other attributes such as xsi:type (ns:type is not to be confused with xsi:type).
Default values can be associated with any field that has a primitive type in a struct/class, as is illustrated in this example. The default values are used when the receiving message does not contain the corresponding values.
String attributes are optional. Other type of attributes should be declared as pointers to make them optional:

struct ns__myStruct
{
   @int *a; // omitted when NULL };

Because a remote method request and response is essentially a struct, XML attributes can also be associated with method requests and responses. For example

int ns__myMethod(@char *ns__name, ...);

Attributes can also be attached to the dynamic arrays, binary types, and wrapper classes/structs of primitive types. Wrapper classes are described in Section 10.3.2. For example

struct xsd__string
{
   char *__item;
   @xsd__boolean flag;
};

and

struct xsd__base64Binary
{
   unsigned char *__ptr;
   int __size;
   @xsd__boolean flag;
};

The attribute declarations MUST follow the __item, __ptr, and __size fields which define the characteristics of wrapper structs/classes and dynamic arrays.
Caution: Do not use XML attributes with SOAP RPC encoding. You can only use attributes with RPC literal encoding.

10.6.8  QName Attributes and Elements

gSOAP ensures the proper decoding of XSD QNames. An element or attribute with type QName (Qualified Name) contains a namespace prefix and a local name. You can declare a QName type as a typedef char *xsd__QName. Values of type QName are internally handled as regular strings. gSOAP takes care of the proper namespace prefix mappings when deserializing QName values. For example

typedef char *xsd__QName;
struct ns__myStruct
{
   xsd__QName elt = "ns:xyz"; // QName element with default value "ns:xyz"
   @xsd__QName att = "ns:abc"; // QName attribute with default value "ns:abc"
};

When the elt and att fields are serialized, their string contents are just transmitted (which means that the application is responsible to ensure proper formatting of the QName strings prior to transmission). When the fields are deserialized however, gSOAP takes care mapping the qualifiers to the appropriate namespace prefixes. Suppose that the inbound value for the elt is x:def, where the namespace name associated with the prefix x matches the namespace name of the prefix ns (as defined in the namespace mapping table). Then, the value is automatically converted into ns:def. If the namespace name is not in the table, then x:def is converted to ÜRI":def where ÜRI" is the namespace URI bound to x in the message received. This enables an application to retrieve the namespace information, whether it is in the namespace mapping table or not.
Note: QName is a pre-defined typedef type and used by gSOAP to (de)serialize SOAP Fault codes which are QName elements.

10.7  Union Serialization

A union is only serialized if the union is used within a struct or class declaration that includes a int __union field that acts as a discriminant or selector for the union fields. The selector stores run-time usage information about the union fields. That is, the selector is used to enumerate the union fields such that the gSOAP engine is able to select the correct union field to serialize.
A union within a struct or class with a selector field represents xs:choice within a Schema complexType component. For example:

struct ns__PO
{ ... };
struct ns__Invoice
{ ... };
union ns__PO_or_Invoice
{
   struct ns__PO po;
   struct ns__Invoice invoice;
}; struct ns__composite
{
   char *name;
   int __union;
   union ns__PO_or_Invoice value;
};

The union ns__PO_or_Invoice is expanded as a xs:choice:

<complexType name="composite»
   <sequence>
      <element name="name" type="xsd:string"/>
      <choice>
         <element name="po" type="ns:PO"/>
         <element name="invoice" type="ns:Invoice"/>
      </choice>
   </sequence>
</complexType>

Therefore, the name of the union and field can be freely chosen. However, the union name should be qualified (as shown in the example) to ensure instances of XML Schemas with elementFormDefault="qualified" are correctly serialized (po and invoice are ns: qualified).
The int __union field selector's values are determined by the soapcpp2 compiler. Each union field name has a selector value formed by:

SOAP_UNION_union-name_field-name

These selector values enumerate the union fields starting with 1. The value 0 can be assigned to omit the serialization of the union, but only if explicitly allowed by validation rules, which requires minOccurs="0" for the xs:choice as follows:

struct ns__composite
{
   char *name;
   int __union 0; // <choice minOccurs="0»
   union ns__PO_or_Invoice value;
};

This way we can treat the union as an optional data item by setting __union=0.
The following example shows how the struct ns__composite instance is initialized for serialization:

struct ns__composite data;
data.name = "...";
data.__union = SOAP_UNION_ns__PO_or_Invoice_po; // select PO
data.value.po.number = ...; // populate the PO

Note that failing to set the selector to a valid union field can lead to a crash of the gSOAP serializer because it will attempt to serialize an invalid union field.
For deserialization of union types, the __union selector will be ser to 0 (when permitted) by the gSOAP deserializer or set to one of the union field selector values as determined by the XML payload.
When more than one union is used in a struct or class, the __union selectors must be renamed to avoid name clashes by using suffixes as in:

struct ns__composite
{
   char *name;
   int __union_value; // added suffix "_value"
   union ns__PO_or_Invoice value;
   int __union_data; // added suffix "_data"
   union ns__Email_or_Fax data;
};

10.8  Serializing Pointer Types

The serialization of a pointer to a data type amounts to the serialization of the data type in SOAP and the SOAP encoded representation of a pointer to the data type is indistinguishable from the encoded representation of the data type pointed to.

10.8.1  Multi-Referenced Data

A data structure pointed to by more than one pointer is serialized as SOAP multi-reference data. This means that the data will be serialized only once and identified with a unique id attribute. The encoding of the pointers to the shared data is done through the use of href attributes to refer to the multi-reference data (also see Section 8.12 on options to control the serialization of multi-reference data). Cyclic C/C++ data structures are encoded with multi-reference SOAP encoding. Consider for example the following a linked list data structure:

typedef char *xsd__string;
struct ns__list
{
   xsd__string value;
   struct ns__list *next;
};

Suppose a cyclic linked list is created. The first node contains the value "abc" and points to a node with value "def" which in turn points to the first node. This is encoded as:

<ns:list id="1" xsi:type="ns:list">
   <value xsi:type="xsd:string">abc</value>
   <next xsi:type="ns:list">
      <value xsi:type="xsd:string">def</value>
      <next href="#1"/>
   </next>
</ns:list>

In case multi-referenced data is received that "does not fit in a pointer-based structure", the data is copied. For example, the following two structs are similar, except that the first uses pointer-based fields while the other uses non-pointer-based fields:

typedef long xsd__int;
struct ns__record
{
   xsd__int *a;
   xsd__int *b;
} P;
struct ns__record
{
   xsd__int a;
   xsd__int b;
} R;
...
   P.a = &n;
   P.b = &n;
...

Since both a and b fields of P point to the same integer, the encoding of P is multi-reference:

<ns:record xsi:type="ns:record">
   <a href="#1"/>
   <b href="#1"/>
</ns:record>
<id id="1" xsi:type="xsd:int">123</id>

Now, the decoding of the content in the R data structure that does not use pointers to integers results in a copy of each multi-reference integer. Note that the two structs resemble the same XML data type because the trailing underscore will be ignored in XML encoding and decoding.

10.8.2  NULL Pointers and Nil Elements

A NULL pointer is not serialized, unless the pointer itself is pointed to by another pointer (but see Section 8.12 to control the serialization of NULLs). For example:

struct X
{
   int *p;
   int **q;
}

Suppose pointer q points to pointer p and suppose p=NULL. In that case the p pointer is serialized as

<... id="123" xsi:nil="true"/>

and the serialization of q refers to href="#123". Note that SOAP 1.1 does not support pointer to pointer types (!), so this encoding is specific to gSOAP. The pointer to pointer encoding is rarely used in codes anyway. More common is a pointer to a data type such as a struct with pointer fields.
Caution: When the deserializer encounters an XML element that has a xsi:nil="true" attribute but the corresponding C++ data is not a pointer or reference, the deserializer will terminate with a SOAP_NULL fault when the SOAP_XML_STRICT flag is set. The types section of a WSDL description contains information on the "nilability" of data.

10.9  Void Pointers

In general, void pointers (void*) cannot be (de)serialized because the type of data referred to is untyped. To enable the (de)serialization of the void pointers that are members of structs or classes, you can insert a int __type field right before the void pointer field. The int __ type field contains run time information on the type of the data pointed to by void* member in a struct/class to enable the (de)serialization of this data. The int __type field is set to a SOAP_TYPE_X value, where X is the name of a type. gSOAP generates the SOAP_TYPE_X definitions in soapH.h and uses them internally to uniquely identify the type of each object. The type naming conventions outlined in Section 7.5.1 are used to determine the type name for X.
Here is an example to illustrate the (de)serialization of a void* field in a struct:

struct myStruct
{
   int __type; // the SOAP_TYPE pointed to by p
   void *p;
};

The __type integer can be set to 0 at run time to omit the serialization of the void pointer field.
The following example illustrates the initialization of myStruct with a void pointer to an int:

struct myStruct S;
int n;
S.p = &n;
S.__type = SOAP_TYPE_int;

The serialized output of S contains the integer.
The deserializer for myStruct will automatically set the __type field and void pointer to the deserialized data, provided that the XML content for p carries the xsi:type attribute from which gSOAP can determine the type.
Important: when (de)serializing strings via a void* field, the void* pointer MUST directly point to the string value rather than indirectly as with all other types. For example:

struct myStruct S;
S.p = (void*)"Hello";
S.__type = SOAP_TYPE_string;

This is the case for all string-based types, including types defined with typedef char*.
You may use an arbitrary suffix with the __type fields to handle multiple void pointers in structs/classes. For example

struct myStruct
{
   int __typeOfp; // the SOAP_TYPE pointed to by p
   void *p;
   int __typeOfq; // the SOAP_TYPE pointed to by q
   void *q;
};

Because service method parameters are stored within structs, you can use __type and void* parameters to pass polymorphic arguments without having to define a C++ class hierarchy (Section 10.6.6). For example:

typedef char *xsd__string;
typedef int xsd__int;
typedef float xsd__float;
enum ns__status { on, off };
struct ns__widget { xsd__string name; xsd__int part; }; int ns__myMethod(int __type, void *data, struct ns__myMethodResponse { int __type; void *return_; } *out);

This method has a polymorphic input parameter data and a polymorphic output parameter return_. The __type parameters can be one of SOAP_TYPE_xsd__string, SOAP_TYPE_xsd__int, SOAP_TYPE_xsd__float, SOAP_TYPE_ns__status, or SOAP_TYPE_ns__widget. The WSDL produced by the gSOAP compiler declares the polymorphic parameters of type xsd:anyType which is "too loose" and doesn't allow the gSOAP importer to handle the WSDL accurately. Future gSOAP releases might replace xsd:anyType with a choice schema type that limits the choice of types to the types declared in the header file.

10.10  Fixed-Size Arrays

Fixed size arrays are encoded as per SOAP 1.1 one-dimensional array types. Multi-dimensional fixed size arrays are encoded by gSOAP as nested one-dimensional arrays in SOAP. Encoding of fixed size arrays supports partially transmitted and sparse array SOAP formats.
The decoding of (multi-dimensional) fixed-size arrays supports the SOAP multi-dimensional array format as well as partially transmitted and sparse array formats.
An example:

// Contents of header file "fixed.h":
struct Example
{
   float a[2][3];
};

This specifies a fixed-size array part of the struct Example. The encoding of array a is:

<a xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="float[][2]">
<SOAP-ENC:Array xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="float[3]"
<float xsi:type="float">...</float>
<float xsi:type="float">...</float>
<float xsi:type="float">...</float>
</SOAP-ENC:Array>
<SOAP-ENC:Array xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="float[3]"
<float xsi:type="float">...</float>
<float xsi:type="float">...</float>
<float xsi:type="float">...</float>
</SOAP-ENC:Array>
</a>

Caution: Any decoded parts of a (multi-dimensional) array that do not "fit" in the fixed size array are ignored by the deserializer.

10.11  Dynamic Arrays

As the name suggests, dynamic arrays are much more flexible than fixed-size arrays and dynamic arrays are better adaptable to the SOAP encoding and decoding rules for arrays. In addition, a typical C application allocates a dynamic array using malloc, assigns the location to a pointer variable, and deallocates the array later with free. A typical C++ application allocates a dynamic array using new, assigns the location to a pointer variable, and deallocates the array later with delete. Such dynamic allocations are flexible, but pose a problem for the serialization of data: how does the array serializer know the length of the array to be serialized given only a pointer to the sequence of elements? The application stores the size information somewhere. This information is crucial for the array serializer and has to be made explicitly known to the array serializer by packaging the pointer and array size information within a struct or class.

10.11.1  SOAP Array Bounds Limits

SOAP encoded arrays use the SOAP-ENC:Array type and the SOAP-ENC:arrayType attribute to define the array dimensionality and size. As a security measure to avoid denial of service attacks based on sending a huge array size value requiring the allocation of large chunks of memory, the total number of array elements set by the SOAP-ENC:arrayType attribute cannot exceed SOAP_MAXARRAYSIZE, which is set to 100,000 by default. This constant is defined in stdsoap2.h. This constant only affects multi-dimensional arrays and the dimensionality of the receiving array will be lost when the number of elements exceeds 100,000. One-dimensional arrays will be populated in sequential order as expected.

10.11.2  One-Dimensional Dynamic Arrays

A special form of struct or class is used for one-dimensional dynamic arrays that contains a pointer variable and a field that records the number of elements the pointer points to in memory.
The general form of the struct declaration for one-dimensional dynamic SOAP arrays is:

struct some_name
{
   Type *__ptr; // pointer to array
   int __size; // number of elements pointed to
   [[static const] int __offset [= ...];] // optional SOAP 1.1 array offset
   ... // anything that follows here will be ignored
};

where Type MUST be a type associated with an XML Schema or MUST be a primitive type. If these conditions are not met, a vector-like XML (de)serialization is used (see Section 10.11.7). A primitive type can be used with or without a typedef. If the array elements are structs or classes, then the struct/class type names should have a namespace prefix for schema association, or they should be other (nested) dynamic arrays.
An alternative to a struct is to use a class with optional methods that MUST appear after the __ptr and __size fields:

class some_name
{
   public:
   Type *__ptr;
   int __size;
   [[static const] int __offset [= ...];]
   method1;
   method2;
   ... // any fields that follow will be ignored
};

To encode the data type as an array, the name of the struct or class SHOULD NOT have a namespace prefix, otherwise the data type will be encoded and decoded as a generic vector, see Section 10.11.7.
The deserializer of a dynamic array can decode partially transmitted and/or SOAP sparse arrays, and even multi-dimensional arrays which will be collapsed into a one-dimensional array with row-major ordering.
Caution: SOAP 1.2 does not support partially transmitted arrays. So the __offset field of a dynamic array is ignored.

10.11.3  Example

The following example header file specifies the XMethods Service Listing service getAllSOAPServices remote method and an array of SOAPService data structures:

// Contents of file "listing.h":
class ns3__SOAPService
{
   public:
   int ID;
   char *name;
   char *owner;
   char *description;
   char *homepageURL;
   char *endpoint;
   char *SOAPAction;
   char *methodNamespaceURI;
   char *serviceStatus;
   char *methodName;
   char *dateCreated;
   char *downloadURL;
   char *wsdlURL;
   char *instructions;
   char *contactEmail;
   char *serverImplementation;
};
class ServiceArray
{
   public:
   ns3__SOAPService *__ptr; // points to array elements
   int __size; // number of elements pointed to
   ServiceArray();
   ~ServiceArray();
   void print();
};
int ns__getAllSOAPServices(ServiceArray &return_);

An example client application:

#include "soapH.h" ...
// ServiceArray class method implementations:
ServiceArray::ServiceArray()
{
   __ptr = NULL;
   __size = 0;
}
ServiceArray::~ServiceArray()
{ // destruction handled by gSOAP
}
void ServiceArray::print()
{
   for (int i = 0; i < __size; i++)
      cout << __ptr[i].name << ": " << __ptr[i].homepage << endl;
}
...
// Request a service listing and display results:
{
   struct soap soap;
   ServiceArray result;
   const char *endpoint = "www.xmethods.net:80/soap/servlet/rpcrouter";
   const char *action = "urn:xmethodsServicesManager#getAllSOAPServices";
   ...
   soap_init(&soap);
   soap_call_ns__getAllSOAPServices(&soap, endpoint, action, result);
   result.print();
   ...
   soap_destroy(&soap); // dealloc class instances
   soap_end(&soap); // dealloc deserialized data
   soap_done(&soap); // cleanup and detach soap struct
}

10.11.4  One-Dimensional Dynamic Arrays With Non-Zero Offset

The declaration of a dynamic array as described in 10.11 MAY include an int __offset field. When set to an integer value, the serializer of the dynamic array will use this field as the start index of the array and the SOAP array offset attribute will be used in the SOAP payload. Note that array offsets is a SOAP 1.1 specific feature which is not supported in SOAP 1.2.
For example, the following header file declares a mathematical Vector class, which is a dynamic array of floating point values with an index that starts at 1:

// Contents of file "vector.h":
typedef float xsd__float;
class Vector
{
   xsd__float *__ptr;
   int __size;
   int __offset;
   Vector();
   Vector(int n);
   float& operator[](int i);
}

The implementations of the Vector methods are:

Vector::Vector()
{
   __ptr = NULL;
   __size = 0;
   __offset = 1;
}
Vector::Vector(int n)
{
   __ptr = (float*)malloc(n*sizeof(float));
   __size = n;
   __offset = 1;
}
Vector::~Vector()
{
   if (__ptr)
      free(__ptr);
}
float& Vector::operator[](int i)
{
   return __ptr[i-__offset];
}

An example program fragment that serializes a vector of 3 elements:

struct soap soap;
soap_init(&soap);
Vector v(3);
v[1] = 1.0;
v[2] = 2.0;
v[3] = 3.0;
soap_begin(&soap);
v.serialize(&soap);
v.put("vec");
soap_end(&soap);

The output is a partially transmitted array:

<vec xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:float[4]" SOAP-ENC:offset="[1]">
<item xsi:type="xsd:float">1.0</item>
<item xsi:type="xsd:float">2.0</item>
<item xsi:type="xsd:float">3.0</item>
</vec>

Note that the size of the encoded array is necessarily set to 4 and that the encoding omits the non-existent element at index 0.
The decoding of a dynamic array with an __offset field is more efficient than decoding a dynamic array without an __offset field, because the __offset field will be assigned the value of the SOAP-ENC:offset attribute instead of padding the initial part of the array with default values.

10.11.5  Nested One-Dimensional Dynamic Arrays

One-dimensional dynamic arrays MAY be nested. For example, using class Vector declared in the previous section, class Matrix is declared:

// Contents of file "matrix.h":
class Matrix
{
   public:
   Vector *__ptr;
   int __size;
   int __offset;
   Matrix();
   Matrix(int n, int m);
   ~Matrix();
   Vector& operator[](int i);
};

The Matrix type is essentially an array of pointers to arrays which make up the rows of a matrix. The encoding of the two-dimensional dynamic array in SOAP will be in nested form.

10.11.6  Multi-Dimensional Dynamic Arrays

The general form of the struct declaration for K-dimensional (K > 1) dynamic arrays is:

struct some_name
{
   Type *__ptr;
   int __size[K];
   int __offset[K];
   ... // anything that follows here will be ignored
};

where Type MUST be a type associated with an XML Schema, which means that it must be a typedefed type in case of a primitive type, or a struct/class name with a namespace prefix for schema association, or another dynamic array. If these conditions are not met, a generic vector XML (de)serialization is used (see Section 10.11.7).
An alternative is to use a class with optional methods:

class some_name
{
   public:
   Type *__ptr;
   int __size[K];
   int __offset[K];
   method1;
   method2;
   ... // any fields that follow will be ignored
};

In the above, K is a constant denoting the number of dimensions of the multi-dimensional array.
To encode the data type as an array, the name of the struct or class SHOULD NOT have a namespace prefix, otherwise the data type will be encoded and decoded as a generic vector, see Section 10.11.7.
The deserializer of a dynamic array can decode partially transmitted multi-dimensional arrays.
For example, the following declaration specifies a matrix class:

typedef double xsd__double;
class Matrix
{
   public:
   xsd__double *__ptr;
   int __size[2];
   int __offset[2];
};

In contrast to the matrix class of Section 10.11.5 that defined a matrix as an array of pointers to matrix rows, this class has one pointer to a matrix stored in row-major order. The size of the matrix is determined by the __size field: __size[0] holds the number of rows and __size[1] holds the number of columns of the matrix. Likewise, __ offset[0] is the row offset and __offset[1] is the columns offset.

10.11.7  Encoding XML Generics Containing Dynamic Arrays

XML "generics" extend the concept of a struct by allowing repetitions of elements within the struct. A simple generic is an array-like data structure with a repetition of one element. To achieve this, declare a dynamic array as a struct or class with a name that is qualified with a namespace prefix. SOAP arrays are declared without prefix.
For example:

struct ns__Map
{
   struct ns__Binding {char *key; char *val;} *__ptr;
   int __size;
};

This declares a dynamic array, but the array will be serialized and deserialized as a generic with a list-like data structure. For example:

<ns:Map xsi:type="ns:Map">
<ns:Binding xsi:type="ns:Binding">
<key>Joe</key>
<val>555 77 1234</val>
</ns:Binding>
<ns:Binding xsi:type="ns:Binding">
<key>Susan</key>
<val>555 12 6725</val>
</ns:Binding>
<ns:Binding xsi:type="ns:Binding">
<key>Pete</key>
<val>555 99 4321</val>
</ns:Binding>
</ns:Map>

Deserialization is less efficient compared to an array, because the size of the list is not part of the SOAP encoding. Internal buffering is used by the deserializer to collect the elements. When the end of the list is reached, the buffered elements are copied to a newly allocated space on the heap for the dynamic array.
Multiple arrays can be used in a struct/class to support the concept of generics. Each array results in a repetition of elements in the struct/class. This is achieved with a int __size field in the struct/class where the next field (i.e. below the __size field) is a pointer type. The pointer type is assumed to point to an array of values at run time. The __size field holds the number of values at run time. Multiple arrays can be embedded in a struct/class with __size fields that have a distinct names. To make the __size fields distinct, you can end them with a unique name suffix such as __sizeOfstrings, for example.
The general convention for embedding arrays is:

struct ns__SomeStruct
{
   ...
   int __sizename1; // number of elements pointed to
   Type1 *field1; // by this field
   ...
   int __sizename2; // number of elements pointed to
   Type2 *field2; // by this field
   ...
};

where name1 and name2 are identifiers used as a suffix to distinguish the __ size field. These names can be arbitrary and are not visible in XML.
For example, the following struct has two embedded arrays:

struct ns__Contact
{
   char *firstName;
   char *lastName;
   int __sizePhones;
   ULONG64 *phoneNumber; // array of phone numbers
   int __sizeEmails;
   char **emailAddress; // array of email addresses
   char *socSecNumber;
};

The XML serialization of an example ns__Contact is:

<mycontact xsi:type="ns:Contact">
   <firstName>Joe</firstName>
   <lastName>Smith</lastName>
   <phoneNumber>5551112222</phoneNumber>
   <phoneNumber>5551234567</phoneNumber>
   <phoneNumber>5552348901</phoneNumber>
   <emailAddress>Joe.Smith@mail.com</emailAddress>
   <emailAddress>Joe@Smith.com</emailAddress>
   <socSecNumber>999999999</socSecNumber>
</mycontact>

10.11.8  STL Containers

gSOAP supports the STL containers std::deque, std::list, std::set, and std::vector.
STL containers can only be used within classes to declare members that contain multiple values. This is somewhat similar to the embedding of arrays in structs in C as explained in Section 10.11.7, but the STL container approach is more flexible.
You need to import stldeque.h, stllist.h, stlset.h, or stlvector.h to enable std::deque, std::list, std::set, and std::vector (de)serialization. Here is an example:

#import "stlvector.h"
class ns__myClass
{ public:
   std::vector < int > *number;
   std::vector < xsd__string > *name;
   ...
};

The use of pointer members is not required but advised. The reason is that interoperability with other SOAP toolkits may lead to copying of ns__ myClass instances at run time when (de)serializing multi-referenced data. When a copy is made, certain parts of the containers will be shared between the copies which could lead to disaster when the classes with their containers are deallocated. Another way to avoid this is to declare class ns__myClass within other data types via a pointer. (Interoperability between gSOAP clients and services does not lead to copying.)
The XML Schema that corresponds to the ns__myClass type is

<complexType name="myClass»
   <sequence>
      <element name="number" type="xsd:int" minOccurs="1" maxOccurs="unbounded"/>
      <element name="name" type="xsd:string" minOccurs="1" maxOccurs="unbounded"/>
      ...
   </sequence>
</complexType>

You can specify the minOccurs and maxOccurs values as explained in Section 18.2.
You can also implement your own containers similar to STL containers. The containers must be class templates and should define an iterator type, and void clear(), iterator begin(), iterator end(), and iterator insert(iterator pos, const_reference val). The iterator should have a dereference operator to access the container's elements. The dereference operator is used by gSOAP to send a sequence of XML element values. The insert method can be used as a setter method. gSOAP reads a sequence of XML element values and inserts them in the container via this method.
Here is in example user-defined container template class:

// simpleVector.h
template  < class T >
class simpleVector
{
public:
   typedef T value_type;
   typedef value_type * pointer;
   typedef const value_type * const_pointer;
   typedef value_type & reference;
   typedef const value_type & const_reference;
   typedef pointer iterator;
   typedef const_pointer const_iterator;
protected:
   iterator start;
   iterator finish;
   size_t length;
public:
   simpleVector() { clear(); }
   ~simpleVector() { delete[] start; }
   void\ clear() { start = finish = NULL; }
   iterator begin() { return start; }
   const_iterator begin() const\ { return start; }
   iterator end() { return finish; }
   const_iterator end() const\ { return finish; }
   size_t size() const\ { return finish-start; }
   iterator insert(iterator pos, const_reference val)
      {
         if (!start)
            start = finish = new value_type[length = 4];
         else if (finish > = start + length)
         {
            iterator i = start;
            iterator j = new value_type[2 * length];
            start = j;
            finish = start + length;
            length *= 2;
            if (pos)
               pos = j + (pos - i);
            while (i != finish)
               *j++ = *i++;
         }
         if (pos && pos != finish)
         { iterator i = finish;
            iterator j = i - 1;
            while (j != pos)
               *i- = *j-;
         }
         *finish++ = val;
         return pos;
      }
};

To enable the container, we add the following two lines to our gSOAP header file:

#include "simpleVector.h"
template  < class T > class simpleVector;

The container class should not be defined in the gSOAP header file. It must be defined in a separate header file (e.g. "simpleVector.h"). The template  < class T > class simpleVector declaration ensures that gSOAP will recognize simpleVector as a container class.
Caution: when parsing XML content the container elements may not be stored in the same order given in the XML content. When gSOAP parses XML it uses the insert container methods to store elements one by one. However, element content that is "forwarded" with href attributes will be appended to the container. Forwarding can take place with multi-referenced data that is referred to from the main part of the SOAP 1.1 XML message to the independent elements that carry ids. Therefore, your application should not rely on the preservation of the order of elements in a container.

10.11.9  Polymorphic Dynamic Arrays and Lists

Polymorphic arrays (arrays of polymorphic element types) can be encoded when declared as an array of pointers to class instances. and lists. For example:

class ns__Object
{
   public:
   ...
};
class ns__Data: public ns__Object
{
   public:
   ...
};
class ArrayOfObject
{
   public:
   ns__Object **__ptr; // pointer to array of pointers to Objects
   int __size; // number of Objects pointed to
   int __offset; // optional SOAP 1.1 array offset
};

The pointers in the array can point to the ns__Object base class or ns__Data derived class instances which will be serialized and deserialized accordingly in SOAP. That is, the array elements are polymorphic.

10.11.10  How to Change the Tag Names of the Elements of a SOAP Array or List

The __ptr field in a struct or class declaration of a dynamic array may have an optional suffix part that describes the name of the tags of the SOAP array XML elements. The suffix is part of the field name:

Type *__ptrarray_elt_name

The suffix describes the tag name to be used for all array elements. The usual identifier to XML translations apply, see Section 9.3. The default XML element tag name for array elements is item (which corresponds to the use of field name __ptritem).
Consider for example:

struct ArrayOfstring
{
   xsd__string *__ptrstring;    int __size; };

The array is serialized as:

<array xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:string[2]»
<string xsi:type="xsd:string»Hello</string>
<string xsi:type="xsd:string»World</string>
</array>

SOAP 1.1 and 1.2 do not require the use of a specific tag name for array elements. gSOAP will deserialize a SOAP array while ignoring the tag names. Certain XML Schemas used in doc/literal encoding may require the declaration of array element tag names.

10.12  Base64Binary XML Schema Type Encoding

The base64Binary XML Schema type is a special form of dynamic array declared with a pointer (__ptr) to an unsigned char array.
For example using a struct:

struct xsd__base64Binary
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.
The SOAP_ENC:base64 encoding is another type for base 64 binary encoding specified by the SOAP data type schema and some SOAP applications may use this form (as indicated by their WSDL descriptions). It is declared by:

struct SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate SOAP-ENC:base64 serializers and deserializers.
The advantage of using a class is that methods can be used to initialize and manipulate the __ptr and __size fields. The user can add methods to this class to do this. For example:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
   xsd__base64Binary(); // Constructor
   xsd__base64Binary(struct soap *soap, int n); // Constructor
   ~xsd__base64Binary(); // Destructor
   unsigned char *location(); // returns the memory location
   int size(); // returns the number of bytes
};

Here are example method implementations:

xsd__base64Binary::xsd__base64Binary()
{
   __ptr = NULL;
   __size = 0;
}
xsd__base64Binary::xsd__base64Binary(struct soap *soap, int n)
{
   __ptr = (unsigned char*)soap_malloc(soap, n);
   __size = n;
}
xsd__base64Binary::~xsd__base64Binary()
{ }
unsigned char *xsd__base64Binary::location()
{
   return __ptr;
}
int xsd__base64Binary::size()
{
   return __size;
}

The following example in C/C++ reads from a raw image file and encodes the image in SOAP using the base64Binary type:

...
FILE *fd = fopen("image.jpg", "rb");
xsd__base64Binary image(&soap, filesize(fd));
fread(image.location(), image.size(), 1, fd);
fclose(fd);
soap_begin(&soap);
image.soap_serialize(&soap);
image.soap_put(&soap, "jpegimage", NULL);
soap_end(&soap);
...

where filesize is a function that returns the size of a file given a file descriptor.
Reading the xsd:base64Binary encoded image.

...
xsd__base64Binary image;
soap_begin(&soap);
image.get(&soap, "jpegimage");
soap_end(&soap);
...

The struct or class name soap_enc__base64 should be used for SOAP-ENC:base64 schema type instead of xsd__base64Binary.

10.13  hexBinary XML Schema Type Encoding

The hexBinary XML Schema type is a special form of dynamic array declared with the name xsd__hexBinary and a pointer (__ptr) to an unsigned char array.
For example, using a struct:

struct xsd__hexBinary
{
   unsigned char *__ptr;
   int __size;
};

Or using a class:

class xsd__hexBinary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.

10.14  Literal XML Encoding Style

gSOAP supports document/literal encoding by default. Just as with SOAP RPC encoding, literal encoding requires the XML Schema of the message data to be provided e.g. in WSDL in order for the gSOAP compiler to generate the (de)serialization routines. Alternatively, the optional DOM parser (dom.c and dom++.cpp) can be used to handle generic XML or arbitrary XML documents can be (de)serialized into regular C strings or wide character strings (wchar_t*) by gSOAP (see Section 10.14.1).
The //gsoap service encoding, //gsoap service method-encoding, and //gsoap service method-response-encoding directives explicitly enable SOAP encoded or literal encoded messages. For example, to enable RPC encoding style for the entire service, use:

//gsoap ns service encoding: encoded

To enable encoding for particular service methods, use:

//gsoap ns service method-encoding: myMethod encoded
int ns__myMethod(...)

To enable encoding for particular service methods responses when the method request is literal, use:

//gsoap ns service method-response-encoding: myMethod encoded
int ns__myMethod(...)

Instead of the encoded value, you can use literal, or a specific encoding style value.
Consider the following example that uses the directive to make the literal encoding explicit
   typedef pointer iterator;
   typedef const_pointer const_iterator;
protected:
   iterator start;
   iterator finish;
   size_t length;
public:
   simpleVector() { clear(); }
   ~simpleVector() { delete[] start; }
   void\ clear() { start = finish = NULL; }
   iterator begin() { return start; }
   const_iterator begin() const\ { return start; }
   iterator end() { return finish; }
   const_iterator end() const\ { return finish; }
   size_t size() const\ { return finish-start; }
   iterator insert(iterator pos, const_reference val)
      {
         if (!start)
            start = finish = new value_type[length = 4];
         else if (finish > = start + length)
         {
            iterator i = start;
            iterator j = new value_type[2 * length];
            start = j;
            finish = start + length;
            length *= 2;
            if (pos)
               pos = j + (pos - i);
            while (i != finish)
               *j++ = *i++;
         }
         if (pos && pos != finish)
         { iterator i = finish;
            iterator j = i - 1;
            while (j != pos)
               *i- = *j-;
         }
         *finish++ = val;
         return pos;
      }
};
To enable the container, we add the following two lines to our gSOAP header file:

#include "simpleVector.h"
template  < class T > class simpleVector;

The container class should not be defined in the gSOAP header file. It must be defined in a separate header file (e.g. "simpleVector.h"). The template  < class T > class simpleVector declaration ensures that gSOAP will recognize simpleVector as a container class.
Caution: when parsing XML content the container elements may not be stored in the same order given in the XML content. When gSOAP parses XML it uses the insert container methods to store elements one by one. However, element content that is "forwarded" with href attributes will be appended to the container. Forwarding can take place with multi-referenced data that is referred to from the main part of the SOAP 1.1 XML message to the independent elements that carry ids. Therefore, your application should not rely on the preservation of the order of elements in a container.

10.11.9  Polymorphic Dynamic Arrays and Lists

Polymorphic arrays (arrays of polymorphic element types) can be encoded when declared as an array of pointers to class instances. and lists. For example:

class ns__Object
{
   public:
   ...
};
class ns__Data: public ns__Object
{
   public:
   ...
};
class ArrayOfObject
{
   public:
   ns__Object **__ptr; // pointer to array of pointers to Objects
   int __size; // number of Objects pointed to
   int __offset; // optional SOAP 1.1 array offset
};

The pointers in the array can point to the ns__Object base class or ns__Data derived class instances which will be serialized and deserialized accordingly in SOAP. That is, the array elements are polymorphic.

10.11.10  How to Change the Tag Names of the Elements of a SOAP Array or List

The __ptr field in a struct or class declaration of a dynamic array may have an optional suffix part that describes the name of the tags of the SOAP array XML elements. The suffix is part of the field name:

Type *__ptrarray_elt_name

The suffix describes the tag name to be used for all array elements. The usual identifier to XML translations apply, see Section 9.3. The default XML element tag name for array elements is item (which corresponds to the use of field name __ptritem).
Consider for example:

struct ArrayOfstring
{
   xsd__string *__ptrstring;    int __size; };

The array is serialized as:

<array xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:string[2]»
<string xsi:type="xsd:string»Hello</string>
<string xsi:type="xsd:string»World</string>
</array>

SOAP 1.1 and 1.2 do not require the use of a specific tag name for array elements. gSOAP will deserialize a SOAP array while ignoring the tag names. Certain XML Schemas used in doc/literal encoding may require the declaration of array element tag names.

10.12  Base64Binary XML Schema Type Encoding

The base64Binary XML Schema type is a special form of dynamic array declared with a pointer (__ptr) to an unsigned char array.
For example using a struct:

struct xsd__base64Binary
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.
The SOAP_ENC:base64 encoding is another type for base 64 binary encoding specified by the SOAP data type schema and some SOAP applications may use this form (as indicated by their WSDL descriptions). It is declared by:

struct SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate SOAP-ENC:base64 serializers and deserializers.
The advantage of using a class is that methods can be used to initialize and manipulate the __ptr and __size fields. The user can add methods to this class to do this. For example:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
   xsd__base64Binary(); // Constructor
   xsd__base64Binary(struct soap *soap, int n); // Constructor
   ~xsd__base64Binary(); // Destructor
   unsigned char *location(); // returns the memory location
   int size(); // returns the number of bytes
};

Here are example method implementations:

xsd__base64Binary::xsd__base64Binary()
{
   __ptr = NULL;
   __size = 0;
}
xsd__base64Binary::xsd__base64Binary(struct soap *soap, int n)
{
   __ptr = (unsigned char*)soap_malloc(soap, n);
   __size = n;
}
xsd__base64Binary::~xsd__base64Binary()
{ }
unsigned char *xsd__base64Binary::location()
{
   return __ptr;
}
int xsd__base64Binary::size()
{
   return __size;
}

The following example in C/C++ reads from a raw image file and encodes the image in SOAP using the base64Binary type:

...
FILE *fd = fopen("image.jpg", "rb");
xsd__base64Binary image(&soap, filesize(fd));
fread(image.location(), image.size(), 1, fd);
fclose(fd);
soap_begin(&soap);
image.soap_serialize(&soap);
image.soap_put(&soap, "jpegimage", NULL);
soap_end(&soap);
...

where filesize is a function that returns the size of a file given a file descriptor.
Reading the xsd:base64Binary encoded image.

...
xsd__base64Binary image;
soap_begin(&soap);
image.get(&soap, "jpegimage");
soap_end(&soap);
...

The struct or class name soap_enc__base64 should be used for SOAP-ENC:base64 schema type instead of xsd__base64Binary.

10.13  hexBinary XML Schema Type Encoding

The hexBinary XML Schema type is a special form of dynamic array declared with the name xsd__hexBinary and a pointer (__ptr) to an unsigned char array.
For example, using a struct:

struct xsd__hexBinary
{
   unsigned char *__ptr;
   int __size;
};

Or using a class:

class xsd__hexBinary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.

10.14  Literal XML Encoding Style

gSOAP supports document/literal encoding by default. Just as with SOAP RPC encoding, literal encoding requires the XML Schema of the message data to be provided e.g. in WSDL in order for the gSOAP compiler to generate the (de)serialization routines. Alternatively, the optional DOM parser (dom.c and dom++.cpp) can be used to handle generic XML or arbitrary XML documents can be (de)serialized into regular C strings or wide character strings (wchar_t*) by gSOAP (see Section 10.14.1).
The //gsoap service encoding, //gsoap service method-encoding, and //gsoap service method-response-encoding directives explicitly enable SOAP encoded or literal encoded messages. For example, to enable RPC encoding style for the entire service, use:

//gsoap ns service encoding: encoded

To enable encoding for particular service methods, use:

//gsoap ns service method-encoding: myMethod encoded
int ns__myMethod(...)

To enable encoding for particular service methods responses when the method request is literal, use:

//gsoap ns service method-response-encoding: myMethod encoded
int ns__myMethod(...)

Instead of the encoded value, you can use literal, or a specific encoding style value.
Consider the following example that uses the directive to make the literal encoding explicit
   typedef pointer iterator;
   typedef const_pointer const_iterator;
protected:
   iterator start;
   iterator finish;
   size_t length;
public:
   simpleVector() { clear(); }
   ~simpleVector() { delete[] start; }
   void\ clear() { start = finish = NULL; }
   iterator begin() { return start; }
   const_iterator begin() const\ { return start; }
   iterator end() { return finish; }
   const_iterator end() const\ { return finish; }
   size_t size() const\ { return finish-start; }
   iterator insert(iterator pos, const_reference val)
      {
         if (!start)
            start = finish = new value_type[length = 4];
         else if (finish > = start + length)
         {
            iterator i = start;
            iterator j = new value_type[2 * length];
            start = j;
            finish = start + length;
            length *= 2;
            if (pos)
               pos = j + (pos - i);
            while (i != finish)
               *j++ = *i++;
         }
         if (pos && pos != finish)
         { iterator i = finish;
            iterator j = i - 1;
            while (j != pos)
               *i- = *j-;
         }
         *finish++ = val;
         return pos;
      }
};
To enable the container, we add the following two lines to our gSOAP header file:

#include "simpleVector.h"
template  < class T > class simpleVector;

The container class should not be defined in the gSOAP header file. It must be defined in a separate header file (e.g. "simpleVector.h"). The template  < class T > class simpleVector declaration ensures that gSOAP will recognize simpleVector as a container class.
Caution: when parsing XML content the container elements may not be stored in the same order given in the XML content. When gSOAP parses XML it uses the insert container methods to store elements one by one. However, element content that is "forwarded" with href attributes will be appended to the container. Forwarding can take place with multi-referenced data that is referred to from the main part of the SOAP 1.1 XML message to the independent elements that carry ids. Therefore, your application should not rely on the preservation of the order of elements in a container.

10.11.9  Polymorphic Dynamic Arrays and Lists

Polymorphic arrays (arrays of polymorphic element types) can be encoded when declared as an array of pointers to class instances. and lists. For example:

class ns__Object
{
   public:
   ...
};
class ns__Data: public ns__Object
{
   public:
   ...
};
class ArrayOfObject
{
   public:
   ns__Object **__ptr; // pointer to array of pointers to Objects
   int __size; // number of Objects pointed to
   int __offset; // optional SOAP 1.1 array offset
};

The pointers in the array can point to the ns__Object base class or ns__Data derived class instances which will be serialized and deserialized accordingly in SOAP. That is, the array elements are polymorphic.

10.11.10  How to Change the Tag Names of the Elements of a SOAP Array or List

The __ptr field in a struct or class declaration of a dynamic array may have an optional suffix part that describes the name of the tags of the SOAP array XML elements. The suffix is part of the field name:

Type *__ptrarray_elt_name

The suffix describes the tag name to be used for all array elements. The usual identifier to XML translations apply, see Section 9.3. The default XML element tag name for array elements is item (which corresponds to the use of field name __ptritem).
Consider for example:

struct ArrayOfstring
{
   xsd__string *__ptrstring;    int __size; };

The array is serialized as:

<array xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:string[2]»
<string xsi:type="xsd:string»Hello</string>
<string xsi:type="xsd:string»World</string>
</array>

SOAP 1.1 and 1.2 do not require the use of a specific tag name for array elements. gSOAP will deserialize a SOAP array while ignoring the tag names. Certain XML Schemas used in doc/literal encoding may require the declaration of array element tag names.

10.12  Base64Binary XML Schema Type Encoding

The base64Binary XML Schema type is a special form of dynamic array declared with a pointer (__ptr) to an unsigned char array.
For example using a struct:

struct xsd__base64Binary
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.
The SOAP_ENC:base64 encoding is another type for base 64 binary encoding specified by the SOAP data type schema and some SOAP applications may use this form (as indicated by their WSDL descriptions). It is declared by:

struct SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate SOAP-ENC:base64 serializers and deserializers.
The advantage of using a class is that methods can be used to initialize and manipulate the __ptr and __size fields. The user can add methods to this class to do this. For example:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
   xsd__base64Binary(); // Constructor
   xsd__base64Binary(struct soap *soap, int n); // Constructor
   ~xsd__base64Binary(); // Destructor
   unsigned char *location(); // returns the memory location
   int size(); // returns the number of bytes
};

Here are example method implementations:

xsd__base64Binary::xsd__base64Binary()
{
   __ptr = NULL;
   __size = 0;
}
xsd__base64Binary::xsd__base64Binary(struct soap *soap, int n)
{
   __ptr = (unsigned char*)soap_malloc(soap, n);
   __size = n;
}
xsd__base64Binary::~xsd__base64Binary()
{ }
unsigned char *xsd__base64Binary::location()
{
   return __ptr;
}
int xsd__base64Binary::size()
{
   return __size;
}

The following example in C/C++ reads from a raw image file and encodes the image in SOAP using the base64Binary type:

...
FILE *fd = fopen("image.jpg", "rb");
xsd__base64Binary image(&soap, filesize(fd));
fread(image.location(), image.size(), 1, fd);
fclose(fd);
soap_begin(&soap);
image.soap_serialize(&soap);
image.soap_put(&soap, "jpegimage", NULL);
soap_end(&soap);
...

where filesize is a function that returns the size of a file given a file descriptor.
Reading the xsd:base64Binary encoded image.

...
xsd__base64Binary image;
soap_begin(&soap);
image.get(&soap, "jpegimage");
soap_end(&soap);
...

The struct or class name soap_enc__base64 should be used for SOAP-ENC:base64 schema type instead of xsd__base64Binary.

10.13  hexBinary XML Schema Type Encoding

The hexBinary XML Schema type is a special form of dynamic array declared with the name xsd__hexBinary and a pointer (__ptr) to an unsigned char array.
For example, using a struct:

struct xsd__hexBinary
{
   unsigned char *__ptr;
   int __size;
};

Or using a class:

class xsd__hexBinary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.

10.14  Literal XML Encoding Style

gSOAP supports document/literal encoding by default. Just as with SOAP RPC encoding, literal encoding requires the XML Schema of the message data to be provided e.g. in WSDL in order for the gSOAP compiler to generate the (de)serialization routines. Alternatively, the optional DOM parser (dom.c and dom++.cpp) can be used to handle generic XML or arbitrary XML documents can be (de)serialized into regular C strings or wide character strings (wchar_t*) by gSOAP (see Section 10.14.1).
The //gsoap service encoding, //gsoap service method-encoding, and //gsoap service method-response-encoding directives explicitly enable SOAP encoded or literal encoded messages. For example, to enable RPC encoding style for the entire service, use:

//gsoap ns service encoding: encoded

To enable encoding for particular service methods, use:

//gsoap ns service method-encoding: myMethod encoded
int ns__myMethod(...)

To enable encoding for particular service methods responses when the method request is literal, use:

//gsoap ns service method-response-encoding: myMethod encoded
int ns__myMethod(...)

Instead of the encoded value, you can use literal, or a specific encoding style value.
Consider the following example that uses the directive to make the literal encoding explicit
   typedef pointer iterator;
   typedef const_pointer const_iterator;
protected:
   iterator start;
   iterator finish;
   size_t length;
public:
   simpleVector() { clear(); }
   ~simpleVector() { delete[] start; }
   void\ clear() { start = finish = NULL; }
   iterator begin() { return start; }
   const_iterator begin() const\ { return start; }
   iterator end() { return finish; }
   const_iterator end() const\ { return finish; }
   size_t size() const\ { return finish-start; }
   iterator insert(iterator pos, const_reference val)
      {
         if (!start)
            start = finish = new value_type[length = 4];
         else if (finish > = start + length)
         {
            iterator i = start;
            iterator j = new value_type[2 * length];
            start = j;
            finish = start + length;
            length *= 2;
            if (pos)
               pos = j + (pos - i);
            while (i != finish)
               *j++ = *i++;
         }
         if (pos && pos != finish)
         { iterator i = finish;
            iterator j = i - 1;
            while (j != pos)
               *i- = *j-;
         }
         *finish++ = val;
         return pos;
      }
};
To enable the container, we add the following two lines to our gSOAP header file:

#include "simpleVector.h"
template  < class T > class simpleVector;

The container class should not be defined in the gSOAP header file. It must be defined in a separate header file (e.g. "simpleVector.h"). The template  < class T > class simpleVector declaration ensures that gSOAP will recognize simpleVector as a container class.
Caution: when parsing XML content the container elements may not be stored in the same order given in the XML content. When gSOAP parses XML it uses the insert container methods to store elements one by one. However, element content that is "forwarded" with href attributes will be appended to the container. Forwarding can take place with multi-referenced data that is referred to from the main part of the SOAP 1.1 XML message to the independent elements that carry ids. Therefore, your application should not rely on the preservation of the order of elements in a container.

10.11.9  Polymorphic Dynamic Arrays and Lists

Polymorphic arrays (arrays of polymorphic element types) can be encoded when declared as an array of pointers to class instances. and lists. For example:

class ns__Object
{
   public:
   ...
};
class ns__Data: public ns__Object
{
   public:
   ...
};
class ArrayOfObject
{
   public:
   ns__Object **__ptr; // pointer to array of pointers to Objects
   int __size; // number of Objects pointed to
   int __offset; // optional SOAP 1.1 array offset
};

The pointers in the array can point to the ns__Object base class or ns__Data derived class instances which will be serialized and deserialized accordingly in SOAP. That is, the array elements are polymorphic.

10.11.10  How to Change the Tag Names of the Elements of a SOAP Array or List

The __ptr field in a struct or class declaration of a dynamic array may have an optional suffix part that describes the name of the tags of the SOAP array XML elements. The suffix is part of the field name:

Type *__ptrarray_elt_name

The suffix describes the tag name to be used for all array elements. The usual identifier to XML translations apply, see Section 9.3. The default XML element tag name for array elements is item (which corresponds to the use of field name __ptritem).
Consider for example:

struct ArrayOfstring
{
   xsd__string *__ptrstring;    int __size; };

The array is serialized as:

<array xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:string[2]»
<string xsi:type="xsd:string»Hello</string>
<string xsi:type="xsd:string»World</string>
</array>

SOAP 1.1 and 1.2 do not require the use of a specific tag name for array elements. gSOAP will deserialize a SOAP array while ignoring the tag names. Certain XML Schemas used in doc/literal encoding may require the declaration of array element tag names.

10.12  Base64Binary XML Schema Type Encoding

The base64Binary XML Schema type is a special form of dynamic array declared with a pointer (__ptr) to an unsigned char array.
For example using a struct:

struct xsd__base64Binary
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.
The SOAP_ENC:base64 encoding is another type for base 64 binary encoding specified by the SOAP data type schema and some SOAP applications may use this form (as indicated by their WSDL descriptions). It is declared by:

struct SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate SOAP-ENC:base64 serializers and deserializers.
The advantage of using a class is that methods can be used to initialize and manipulate the __ptr and __size fields. The user can add methods to this class to do this. For example:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
   xsd__base64Binary(); // Constructor
   xsd__base64Binary(struct soap *soap, int n); // Constructor
   ~xsd__base64Binary(); // Destructor
   unsigned char *location(); // returns the memory location
   int size(); // returns the number of bytes
};

Here are example method implementations:

xsd__base64Binary::xsd__base64Binary()
{
   __ptr = NULL;
   __size = 0;
}
xsd__base64Binary::xsd__base64Binary(struct soap *soap, int n)
{
   __ptr = (unsigned char*)soap_malloc(soap, n);
   __size = n;
}
xsd__base64Binary::~xsd__base64Binary()
{ }
unsigned char *xsd__base64Binary::location()
{
   return __ptr;
}
int xsd__base64Binary::size()
{
   return __size;
}

The following example in C/C++ reads from a raw image file and encodes the image in SOAP using the base64Binary type:

...
FILE *fd = fopen("image.jpg", "rb");
xsd__base64Binary image(&soap, filesize(fd));
fread(image.location(), image.size(), 1, fd);
fclose(fd);
soap_begin(&soap);
image.soap_serialize(&soap);
image.soap_put(&soap, "jpegimage", NULL);
soap_end(&soap);
...

where filesize is a function that returns the size of a file given a file descriptor.
Reading the xsd:base64Binary encoded image.

...
xsd__base64Binary image;
soap_begin(&soap);
image.get(&soap, "jpegimage");
soap_end(&soap);
...

The struct or class name soap_enc__base64 should be used for SOAP-ENC:base64 schema type instead of xsd__base64Binary.

10.13  hexBinary XML Schema Type Encoding

The hexBinary XML Schema type is a special form of dynamic array declared with the name xsd__hexBinary and a pointer (__ptr) to an unsigned char array.
For example, using a struct:

struct xsd__hexBinary
{
   unsigned char *__ptr;
   int __size;
};

Or using a class:

class xsd__hexBinary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.

10.14  Literal XML Encoding Style

gSOAP supports document/literal encoding by default. Just as with SOAP RPC encoding, literal encoding requires the XML Schema of the message data to be provided e.g. in WSDL in order for the gSOAP compiler to generate the (de)serialization routines. Alternatively, the optional DOM parser (dom.c and dom++.cpp) can be used to handle generic XML or arbitrary XML documents can be (de)serialized into regular C strings or wide character strings (wchar_t*) by gSOAP (see Section 10.14.1).
The //gsoap service encoding, //gsoap service method-encoding, and //gsoap service method-response-encoding directives explicitly enable SOAP encoded or literal encoded messages. For example, to enable RPC encoding style for the entire service, use:

//gsoap ns service encoding: encoded

To enable encoding for particular service methods, use:

//gsoap ns service method-encoding: myMethod encoded
int ns__myMethod(...)

To enable encoding for particular service methods responses when the method request is literal, use:

//gsoap ns service method-response-encoding: myMethod encoded
int ns__myMethod(...)

Instead of the encoded value, you can use literal, or a specific encoding style value.
Consider the following example that uses the directive to make the literal encoding explicit
   typedef pointer iterator;
   typedef const_pointer const_iterator;
protected:
   iterator start;
   iterator finish;
   size_t length;
public:
   simpleVector() { clear(); }
   ~simpleVector() { delete[] start; }
   void\ clear() { start = finish = NULL; }
   iterator begin() { return start; }
   const_iterator begin() const\ { return start; }
   iterator end() { return finish; }
   const_iterator end() const\ { return finish; }
   size_t size() const\ { return finish-start; }
   iterator insert(iterator pos, const_reference val)
      {
         if (!start)
            start = finish = new value_type[length = 4];
         else if (finish > = start + length)
         {
            iterator i = start;
            iterator j = new value_type[2 * length];
            start = j;
            finish = start + length;
            length *= 2;
            if (pos)
               pos = j + (pos - i);
            while (i != finish)
               *j++ = *i++;
         }
         if (pos && pos != finish)
         { iterator i = finish;
            iterator j = i - 1;
            while (j != pos)
               *i- = *j-;
         }
         *finish++ = val;
         return pos;
      }
};
To enable the container, we add the following two lines to our gSOAP header file:

#include "simpleVector.h"
template  < class T > class simpleVector;

The container class should not be defined in the gSOAP header file. It must be defined in a separate header file (e.g. "simpleVector.h"). The template  < class T > class simpleVector declaration ensures that gSOAP will recognize simpleVector as a container class.
Caution: when parsing XML content the container elements may not be stored in the same order given in the XML content. When gSOAP parses XML it uses the insert container methods to store elements one by one. However, element content that is "forwarded" with href attributes will be appended to the container. Forwarding can take place with multi-referenced data that is referred to from the main part of the SOAP 1.1 XML message to the independent elements that carry ids. Therefore, your application should not rely on the preservation of the order of elements in a container.

10.11.9  Polymorphic Dynamic Arrays and Lists

Polymorphic arrays (arrays of polymorphic element types) can be encoded when declared as an array of pointers to class instances. and lists. For example:

class ns__Object
{
   public:
   ...
};
class ns__Data: public ns__Object
{
   public:
   ...
};
class ArrayOfObject
{
   public:
   ns__Object **__ptr; // pointer to array of pointers to Objects
   int __size; // number of Objects pointed to
   int __offset; // optional SOAP 1.1 array offset
};

The pointers in the array can point to the ns__Object base class or ns__Data derived class instances which will be serialized and deserialized accordingly in SOAP. That is, the array elements are polymorphic.

10.11.10  How to Change the Tag Names of the Elements of a SOAP Array or List

The __ptr field in a struct or class declaration of a dynamic array may have an optional suffix part that describes the name of the tags of the SOAP array XML elements. The suffix is part of the field name:

Type *__ptrarray_elt_name

The suffix describes the tag name to be used for all array elements. The usual identifier to XML translations apply, see Section 9.3. The default XML element tag name for array elements is item (which corresponds to the use of field name __ptritem).
Consider for example:

struct ArrayOfstring
{
   xsd__string *__ptrstring;    int __size; };

The array is serialized as:

<array xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:string[2]»
<string xsi:type="xsd:string»Hello</string>
<string xsi:type="xsd:string»World</string>
</array>

SOAP 1.1 and 1.2 do not require the use of a specific tag name for array elements. gSOAP will deserialize a SOAP array while ignoring the tag names. Certain XML Schemas used in doc/literal encoding may require the declaration of array element tag names.

10.12  Base64Binary XML Schema Type Encoding

The base64Binary XML Schema type is a special form of dynamic array declared with a pointer (__ptr) to an unsigned char array.
For example using a struct:

struct xsd__base64Binary
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.
The SOAP_ENC:base64 encoding is another type for base 64 binary encoding specified by the SOAP data type schema and some SOAP applications may use this form (as indicated by their WSDL descriptions). It is declared by:

struct SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate SOAP-ENC:base64 serializers and deserializers.
The advantage of using a class is that methods can be used to initialize and manipulate the __ptr and __size fields. The user can add methods to this class to do this. For example:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
   xsd__base64Binary(); // Constructor
   xsd__base64Binary(struct soap *soap, int n); // Constructor
   ~xsd__base64Binary(); // Destructor
   unsigned char *location(); // returns the memory location
   int size(); // returns the number of bytes
};

Here are example method implementations:

xsd__base64Binary::xsd__base64Binary()
{
   __ptr = NULL;
   __size = 0;
}
xsd__base64Binary::xsd__base64Binary(struct soap *soap, int n)
{
   __ptr = (unsigned char*)soap_malloc(soap, n);
   __size = n;
}
xsd__base64Binary::~xsd__base64Binary()
{ }
unsigned char *xsd__base64Binary::location()
{
   return __ptr;
}
int xsd__base64Binary::size()
{
   return __size;
}

The following example in C/C++ reads from a raw image file and encodes the image in SOAP using the base64Binary type:

...
FILE *fd = fopen("image.jpg", "rb");
xsd__base64Binary image(&soap, filesize(fd));
fread(image.location(), image.size(), 1, fd);
fclose(fd);
soap_begin(&soap);
image.soap_serialize(&soap);
image.soap_put(&soap, "jpegimage", NULL);
soap_end(&soap);
...

where filesize is a function that returns the size of a file given a file descriptor.
Reading the xsd:base64Binary encoded image.

...
xsd__base64Binary image;
soap_begin(&soap);
image.get(&soap, "jpegimage");
soap_end(&soap);
...

The struct or class name soap_enc__base64 should be used for SOAP-ENC:base64 schema type instead of xsd__base64Binary.

10.13  hexBinary XML Schema Type Encoding

The hexBinary XML Schema type is a special form of dynamic array declared with the name xsd__hexBinary and a pointer (__ptr) to an unsigned char array.
For example, using a struct:

struct xsd__hexBinary
{
   unsigned char *__ptr;
   int __size;
};

Or using a class:

class xsd__hexBinary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.

10.14  Literal XML Encoding Style

gSOAP supports document/literal encoding by default. Just as with SOAP RPC encoding, literal encoding requires the XML Schema of the message data to be provided e.g. in WSDL in order for the gSOAP compiler to generate the (de)serialization routines. Alternatively, the optional DOM parser (dom.c and dom++.cpp) can be used to handle generic XML or arbitrary XML documents can be (de)serialized into regular C strings or wide character strings (wchar_t*) by gSOAP (see Section 10.14.1).
The //gsoap service encoding, //gsoap service method-encoding, and //gsoap service method-response-encoding directives explicitly enable SOAP encoded or literal encoded messages. For example, to enable RPC encoding style for the entire service, use:

//gsoap ns service encoding: encoded

To enable encoding for particular service methods, use:

//gsoap ns service method-encoding: myMethod encoded
int ns__myMethod(...)

To enable encoding for particular service methods responses when the method request is literal, use:

//gsoap ns service method-response-encoding: myMethod encoded
int ns__myMethod(...)

Instead of the encoded value, you can use literal, or a specific encoding style value.
Consider the following example that uses the directive to make the literal encoding explicit
   typedef pointer iterator;
   typedef const_pointer const_iterator;
protected:
   iterator start;
   iterator finish;
   size_t length;
public:
   simpleVector() { clear(); }
   ~simpleVector() { delete[] start; }
   void\ clear() { start = finish = NULL; }
   iterator begin() { return start; }
   const_iterator begin() const\ { return start; }
   iterator end() { return finish; }
   const_iterator end() const\ { return finish; }
   size_t size() const\ { return finish-start; }
   iterator insert(iterator pos, const_reference val)
      {
         if (!start)
            start = finish = new value_type[length = 4];
         else if (finish > = start + length)
         {
            iterator i = start;
            iterator j = new value_type[2 * length];
            start = j;
            finish = start + length;
            length *= 2;
            if (pos)
               pos = j + (pos - i);
            while (i != finish)
               *j++ = *i++;
         }
         if (pos && pos != finish)
         { iterator i = finish;
            iterator j = i - 1;
            while (j != pos)
               *i- = *j-;
         }
         *finish++ = val;
         return pos;
      }
};
To enable the container, we add the following two lines to our gSOAP header file:

#include "simpleVector.h"
template  < class T > class simpleVector;

The container class should not be defined in the gSOAP header file. It must be defined in a separate header file (e.g. "simpleVector.h"). The template  < class T > class simpleVector declaration ensures that gSOAP will recognize simpleVector as a container class.
Caution: when parsing XML content the container elements may not be stored in the same order given in the XML content. When gSOAP parses XML it uses the insert container methods to store elements one by one. However, element content that is "forwarded" with href attributes will be appended to the container. Forwarding can take place with multi-referenced data that is referred to from the main part of the SOAP 1.1 XML message to the independent elements that carry ids. Therefore, your application should not rely on the preservation of the order of elements in a container.

10.11.9  Polymorphic Dynamic Arrays and Lists

Polymorphic arrays (arrays of polymorphic element types) can be encoded when declared as an array of pointers to class instances. and lists. For example:

class ns__Object
{
   public:
   ...
};
class ns__Data: public ns__Object
{
   public:
   ...
};
class ArrayOfObject
{
   public:
   ns__Object **__ptr; // pointer to array of pointers to Objects
   int __size; // number of Objects pointed to
   int __offset; // optional SOAP 1.1 array offset
};

The pointers in the array can point to the ns__Object base class or ns__Data derived class instances which will be serialized and deserialized accordingly in SOAP. That is, the array elements are polymorphic.

10.11.10  How to Change the Tag Names of the Elements of a SOAP Array or List

The __ptr field in a struct or class declaration of a dynamic array may have an optional suffix part that describes the name of the tags of the SOAP array XML elements. The suffix is part of the field name:

Type *__ptrarray_elt_name

The suffix describes the tag name to be used for all array elements. The usual identifier to XML translations apply, see Section 9.3. The default XML element tag name for array elements is item (which corresponds to the use of field name __ptritem).
Consider for example:

struct ArrayOfstring
{
   xsd__string *__ptrstring;    int __size; };

The array is serialized as:

<array xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:string[2]»
<string xsi:type="xsd:string»Hello</string>
<string xsi:type="xsd:string»World</string>
</array>

SOAP 1.1 and 1.2 do not require the use of a specific tag name for array elements. gSOAP will deserialize a SOAP array while ignoring the tag names. Certain XML Schemas used in doc/literal encoding may require the declaration of array element tag names.

10.12  Base64Binary XML Schema Type Encoding

The base64Binary XML Schema type is a special form of dynamic array declared with a pointer (__ptr) to an unsigned char array.
For example using a struct:

struct xsd__base64Binary
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.
The SOAP_ENC:base64 encoding is another type for base 64 binary encoding specified by the SOAP data type schema and some SOAP applications may use this form (as indicated by their WSDL descriptions). It is declared by:

struct SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate SOAP-ENC:base64 serializers and deserializers.
The advantage of using a class is that methods can be used to initialize and manipulate the __ptr and __size fields. The user can add methods to this class to do this. For example:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
   xsd__base64Binary(); // Constructor
   xsd__base64Binary(struct soap *soap, int n); // Constructor
   ~xsd__base64Binary(); // Destructor
   unsigned char *location(); // returns the memory location
   int size(); // returns the number of bytes
};

Here are example method implementations:

xsd__base64Binary::xsd__base64Binary()
{
   __ptr = NULL;
   __size = 0;
}
xsd__base64Binary::xsd__base64Binary(struct soap *soap, int n)
{
   __ptr = (unsigned char*)soap_malloc(soap, n);
   __size = n;
}
xsd__base64Binary::~xsd__base64Binary()
{ }
unsigned char *xsd__base64Binary::location()
{
   return __ptr;
}
int xsd__base64Binary::size()
{
   return __size;
}

The following example in C/C++ reads from a raw image file and encodes the image in SOAP using the base64Binary type:

...
FILE *fd = fopen("image.jpg", "rb");
xsd__base64Binary image(&soap, filesize(fd));
fread(image.location(), image.size(), 1, fd);
fclose(fd);
soap_begin(&soap);
image.soap_serialize(&soap);
image.soap_put(&soap, "jpegimage", NULL);
soap_end(&soap);
...

where filesize is a function that returns the size of a file given a file descriptor.
Reading the xsd:base64Binary encoded image.

...
xsd__base64Binary image;
soap_begin(&soap);
image.get(&soap, "jpegimage");
soap_end(&soap);
...

The struct or class name soap_enc__base64 should be used for SOAP-ENC:base64 schema type instead of xsd__base64Binary.

10.13  hexBinary XML Schema Type Encoding

The hexBinary XML Schema type is a special form of dynamic array declared with the name xsd__hexBinary and a pointer (__ptr) to an unsigned char array.
For example, using a struct:

struct xsd__hexBinary
{
   unsigned char *__ptr;
   int __size;
};

Or using a class:

class xsd__hexBinary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.

10.14  Literal XML Encoding Style

gSOAP supports document/literal encoding by default. Just as with SOAP RPC encoding, literal encoding requires the XML Schema of the message data to be provided e.g. in WSDL in order for the gSOAP compiler to generate the (de)serialization routines. Alternatively, the optional DOM parser (dom.c and dom++.cpp) can be used to handle generic XML or arbitrary XML documents can be (de)serialized into regular C strings or wide character strings (wchar_t*) by gSOAP (see Section 10.14.1).
The //gsoap service encoding, //gsoap service method-encoding, and //gsoap service method-response-encoding directives explicitly enable SOAP encoded or literal encoded messages. For example, to enable RPC encoding style for the entire service, use:

//gsoap ns service encoding: encoded

To enable encoding for particular service methods, use:

//gsoap ns service method-encoding: myMethod encoded
int ns__myMethod(...)

To enable encoding for particular service methods responses when the method request is literal, use:

//gsoap ns service method-response-encoding: myMethod encoded
int ns__myMethod(...)

Instead of the encoded value, you can use literal, or a specific encoding style value.
Consider the following example that uses the directive to make the literal encoding explicit
   typedef pointer iterator;
   typedef const_pointer const_iterator;
protected:
   iterator start;
   iterator finish;
   size_t length;
public:
   simpleVector() { clear(); }
   ~simpleVector() { delete[] start; }
   void\ clear() { start = finish = NULL; }
   iterator begin() { return start; }
   const_iterator begin() const\ { return start; }
   iterator end() { return finish; }
   const_iterator end() const\ { return finish; }
   size_t size() const\ { return finish-start; }
   iterator insert(iterator pos, const_reference val)
      {
         if (!start)
            start = finish = new value_type[length = 4];
         else if (finish > = start + length)
         {
            iterator i = start;
            iterator j = new value_type[2 * length];
            start = j;
            finish = start + length;
            length *= 2;
            if (pos)
               pos = j + (pos - i);
            while (i != finish)
               *j++ = *i++;
         }
         if (pos && pos != finish)
         { iterator i = finish;
            iterator j = i - 1;
            while (j != pos)
               *i- = *j-;
         }
         *finish++ = val;
         return pos;
      }
};
To enable the container, we add the following two lines to our gSOAP header file:

#include "simpleVector.h"
template  < class T > class simpleVector;

The container class should not be defined in the gSOAP header file. It must be defined in a separate header file (e.g. "simpleVector.h"). The template  < class T > class simpleVector declaration ensures that gSOAP will recognize simpleVector as a container class.
Caution: when parsing XML content the container elements may not be stored in the same order given in the XML content. When gSOAP parses XML it uses the insert container methods to store elements one by one. However, element content that is "forwarded" with href attributes will be appended to the container. Forwarding can take place with multi-referenced data that is referred to from the main part of the SOAP 1.1 XML message to the independent elements that carry ids. Therefore, your application should not rely on the preservation of the order of elements in a container.

10.11.9  Polymorphic Dynamic Arrays and Lists

Polymorphic arrays (arrays of polymorphic element types) can be encoded when declared as an array of pointers to class instances. and lists. For example:

class ns__Object
{
   public:
   ...
};
class ns__Data: public ns__Object
{
   public:
   ...
};
class ArrayOfObject
{
   public:
   ns__Object **__ptr; // pointer to array of pointers to Objects
   int __size; // number of Objects pointed to
   int __offset; // optional SOAP 1.1 array offset
};

The pointers in the array can point to the ns__Object base class or ns__Data derived class instances which will be serialized and deserialized accordingly in SOAP. That is, the array elements are polymorphic.

10.11.10  How to Change the Tag Names of the Elements of a SOAP Array or List

The __ptr field in a struct or class declaration of a dynamic array may have an optional suffix part that describes the name of the tags of the SOAP array XML elements. The suffix is part of the field name:

Type *__ptrarray_elt_name

The suffix describes the tag name to be used for all array elements. The usual identifier to XML translations apply, see Section 9.3. The default XML element tag name for array elements is item (which corresponds to the use of field name __ptritem).
Consider for example:

struct ArrayOfstring
{
   xsd__string *__ptrstring;    int __size; };

The array is serialized as:

<array xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:string[2]»
<string xsi:type="xsd:string»Hello</string>
<string xsi:type="xsd:string»World</string>
</array>

SOAP 1.1 and 1.2 do not require the use of a specific tag name for array elements. gSOAP will deserialize a SOAP array while ignoring the tag names. Certain XML Schemas used in doc/literal encoding may require the declaration of array element tag names.

10.12  Base64Binary XML Schema Type Encoding

The base64Binary XML Schema type is a special form of dynamic array declared with a pointer (__ptr) to an unsigned char array.
For example using a struct:

struct xsd__base64Binary
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.
The SOAP_ENC:base64 encoding is another type for base 64 binary encoding specified by the SOAP data type schema and some SOAP applications may use this form (as indicated by their WSDL descriptions). It is declared by:

struct SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate SOAP-ENC:base64 serializers and deserializers.
The advantage of using a class is that methods can be used to initialize and manipulate the __ptr and __size fields. The user can add methods to this class to do this. For example:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
   xsd__base64Binary(); // Constructor
   xsd__base64Binary(struct soap *soap, int n); // Constructor
   ~xsd__base64Binary(); // Destructor
   unsigned char *location(); // returns the memory location
   int size(); // returns the number of bytes
};

Here are example method implementations:

xsd__base64Binary::xsd__base64Binary()
{
   __ptr = NULL;
   __size = 0;
}
xsd__base64Binary::xsd__base64Binary(struct soap *soap, int n)
{
   __ptr = (unsigned char*)soap_malloc(soap, n);
   __size = n;
}
xsd__base64Binary::~xsd__base64Binary()
{ }
unsigned char *xsd__base64Binary::location()
{
   return __ptr;
}
int xsd__base64Binary::size()
{
   return __size;
}

The following example in C/C++ reads from a raw image file and encodes the image in SOAP using the base64Binary type:

...
FILE *fd = fopen("image.jpg", "rb");
xsd__base64Binary image(&soap, filesize(fd));
fread(image.location(), image.size(), 1, fd);
fclose(fd);
soap_begin(&soap);
image.soap_serialize(&soap);
image.soap_put(&soap, "jpegimage", NULL);
soap_end(&soap);
...

where filesize is a function that returns the size of a file given a file descriptor.
Reading the xsd:base64Binary encoded image.

...
xsd__base64Binary image;
soap_begin(&soap);
image.get(&soap, "jpegimage");
soap_end(&soap);
...

The struct or class name soap_enc__base64 should be used for SOAP-ENC:base64 schema type instead of xsd__base64Binary.

10.13  hexBinary XML Schema Type Encoding

The hexBinary XML Schema type is a special form of dynamic array declared with the name xsd__hexBinary and a pointer (__ptr) to an unsigned char array.
For example, using a struct:

struct xsd__hexBinary
{
   unsigned char *__ptr;
   int __size;
};

Or using a class:

class xsd__hexBinary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.

10.14  Literal XML Encoding Style

gSOAP supports document/literal encoding by default. Just as with SOAP RPC encoding, literal encoding requires the XML Schema of the message data to be provided e.g. in WSDL in order for the gSOAP compiler to generate the (de)serialization routines. Alternatively, the optional DOM parser (dom.c and dom++.cpp) can be used to handle generic XML or arbitrary XML documents can be (de)serialized into regular C strings or wide character strings (wchar_t*) by gSOAP (see Section 10.14.1).
The //gsoap service encoding, //gsoap service method-encoding, and //gsoap service method-response-encoding directives explicitly enable SOAP encoded or literal encoded messages. For example, to enable RPC encoding style for the entire service, use:

//gsoap ns service encoding: encoded

To enable encoding for particular service methods, use:

//gsoap ns service method-encoding: myMethod encoded
int ns__myMethod(...)

To enable encoding for particular service methods responses when the method request is literal, use:

//gsoap ns service method-response-encoding: myMethod encoded
int ns__myMethod(...)

Instead of the encoded value, you can use literal, or a specific encoding style value.
Consider the following example that uses the directive to make the literal encoding explicit
   typedef pointer iterator;
   typedef const_pointer const_iterator;
protected:
   iterator start;
   iterator finish;
   size_t length;
public:
   simpleVector() { clear(); }
   ~simpleVector() { delete[] start; }
   void\ clear() { start = finish = NULL; }
   iterator begin() { return start; }
   const_iterator begin() const\ { return start; }
   iterator end() { return finish; }
   const_iterator end() const\ { return finish; }
   size_t size() const\ { return finish-start; }
   iterator insert(iterator pos, const_reference val)
      {
         if (!start)
            start = finish = new value_type[length = 4];
         else if (finish > = start + length)
         {
            iterator i = start;
            iterator j = new value_type[2 * length];
            start = j;
            finish = start + length;
            length *= 2;
            if (pos)
               pos = j + (pos - i);
            while (i != finish)
               *j++ = *i++;
         }
         if (pos && pos != finish)
         { iterator i = finish;
            iterator j = i - 1;
            while (j != pos)
               *i- = *j-;
         }
         *finish++ = val;
         return pos;
      }
};
To enable the container, we add the following two lines to our gSOAP header file:

#include "simpleVector.h"
template  < class T > class simpleVector;

The container class should not be defined in the gSOAP header file. It must be defined in a separate header file (e.g. "simpleVector.h"). The template  < class T > class simpleVector declaration ensures that gSOAP will recognize simpleVector as a container class.
Caution: when parsing XML content the container elements may not be stored in the same order given in the XML content. When gSOAP parses XML it uses the insert container methods to store elements one by one. However, element content that is "forwarded" with href attributes will be appended to the container. Forwarding can take place with multi-referenced data that is referred to from the main part of the SOAP 1.1 XML message to the independent elements that carry ids. Therefore, your application should not rely on the preservation of the order of elements in a container.

10.11.9  Polymorphic Dynamic Arrays and Lists

Polymorphic arrays (arrays of polymorphic element types) can be encoded when declared as an array of pointers to class instances. and lists. For example:

class ns__Object
{
   public:
   ...
};
class ns__Data: public ns__Object
{
   public:
   ...
};
class ArrayOfObject
{
   public:
   ns__Object **__ptr; // pointer to array of pointers to Objects
   int __size; // number of Objects pointed to
   int __offset; // optional SOAP 1.1 array offset
};

The pointers in the array can point to the ns__Object base class or ns__Data derived class instances which will be serialized and deserialized accordingly in SOAP. That is, the array elements are polymorphic.

10.11.10  How to Change the Tag Names of the Elements of a SOAP Array or List

The __ptr field in a struct or class declaration of a dynamic array may have an optional suffix part that describes the name of the tags of the SOAP array XML elements. The suffix is part of the field name:

Type *__ptrarray_elt_name

The suffix describes the tag name to be used for all array elements. The usual identifier to XML translations apply, see Section 9.3. The default XML element tag name for array elements is item (which corresponds to the use of field name __ptritem).
Consider for example:

struct ArrayOfstring
{
   xsd__string *__ptrstring;    int __size; };

The array is serialized as:

<array xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:string[2]»
<string xsi:type="xsd:string»Hello</string>
<string xsi:type="xsd:string»World</string>
</array>

SOAP 1.1 and 1.2 do not require the use of a specific tag name for array elements. gSOAP will deserialize a SOAP array while ignoring the tag names. Certain XML Schemas used in doc/literal encoding may require the declaration of array element tag names.

10.12  Base64Binary XML Schema Type Encoding

The base64Binary XML Schema type is a special form of dynamic array declared with a pointer (__ptr) to an unsigned char array.
For example using a struct:

struct xsd__base64Binary
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.
The SOAP_ENC:base64 encoding is another type for base 64 binary encoding specified by the SOAP data type schema and some SOAP applications may use this form (as indicated by their WSDL descriptions). It is declared by:

struct SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate SOAP-ENC:base64 serializers and deserializers.
The advantage of using a class is that methods can be used to initialize and manipulate the __ptr and __size fields. The user can add methods to this class to do this. For example:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
   xsd__base64Binary(); // Constructor
   xsd__base64Binary(struct soap *soap, int n); // Constructor
   ~xsd__base64Binary(); // Destructor
   unsigned char *location(); // returns the memory location
   int size(); // returns the number of bytes
};

Here are example method implementations:

xsd__base64Binary::xsd__base64Binary()
{
   __ptr = NULL;
   __size = 0;
}
xsd__base64Binary::xsd__base64Binary(struct soap *soap, int n)
{
   __ptr = (unsigned char*)soap_malloc(soap, n);
   __size = n;
}
xsd__base64Binary::~xsd__base64Binary()
{ }
unsigned char *xsd__base64Binary::location()
{
   return __ptr;
}
int xsd__base64Binary::size()
{
   return __size;
}

The following example in C/C++ reads from a raw image file and encodes the image in SOAP using the base64Binary type:

...
FILE *fd = fopen("image.jpg", "rb");
xsd__base64Binary image(&soap, filesize(fd));
fread(image.location(), image.size(), 1, fd);
fclose(fd);
soap_begin(&soap);
image.soap_serialize(&soap);
image.soap_put(&soap, "jpegimage", NULL);
soap_end(&soap);
...

where filesize is a function that returns the size of a file given a file descriptor.
Reading the xsd:base64Binary encoded image.

...
xsd__base64Binary image;
soap_begin(&soap);
image.get(&soap, "jpegimage");
soap_end(&soap);
...

The struct or class name soap_enc__base64 should be used for SOAP-ENC:base64 schema type instead of xsd__base64Binary.

10.13  hexBinary XML Schema Type Encoding

The hexBinary XML Schema type is a special form of dynamic array declared with the name xsd__hexBinary and a pointer (__ptr) to an unsigned char array.
For example, using a struct:

struct xsd__hexBinary
{
   unsigned char *__ptr;
   int __size;
};

Or using a class:

class xsd__hexBinary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.

10.14  Literal XML Encoding Style

gSOAP supports document/literal encoding by default. Just as with SOAP RPC encoding, literal encoding requires the XML Schema of the message data to be provided e.g. in WSDL in order for the gSOAP compiler to generate the (de)serialization routines. Alternatively, the optional DOM parser (dom.c and dom++.cpp) can be used to handle generic XML or arbitrary XML documents can be (de)serialized into regular C strings or wide character strings (wchar_t*) by gSOAP (see Section 10.14.1).
The //gsoap service encoding, //gsoap service method-encoding, and //gsoap service method-response-encoding directives explicitly enable SOAP encoded or literal encoded messages. For example, to enable RPC encoding style for the entire service, use:

//gsoap ns service encoding: encoded

To enable encoding for particular service methods, use:

//gsoap ns service method-encoding: myMethod encoded
int ns__myMethod(...)

To enable encoding for particular service methods responses when the method request is literal, use:

//gsoap ns service method-response-encoding: myMethod encoded
int ns__myMethod(...)

Instead of the encoded value, you can use literal, or a specific encoding style value.
Consider the following example that uses the directive to make the literal encoding explicit
   typedef pointer iterator;
   typedef const_pointer const_iterator;
protected:
   iterator start;
   iterator finish;
   size_t length;
public:
   simpleVector() { clear(); }
   ~simpleVector() { delete[] start; }
   void\ clear() { start = finish = NULL; }
   iterator begin() { return start; }
   const_iterator begin() const\ { return start; }
   iterator end() { return finish; }
   const_iterator end() const\ { return finish; }
   size_t size() const\ { return finish-start; }
   iterator insert(iterator pos, const_reference val)
      {
         if (!start)
            start = finish = new value_type[length = 4];
         else if (finish > = start + length)
         {
            iterator i = start;
            iterator j = new value_type[2 * length];
            start = j;
            finish = start + length;
            length *= 2;
            if (pos)
               pos = j + (pos - i);
            while (i != finish)
               *j++ = *i++;
         }
         if (pos && pos != finish)
         { iterator i = finish;
            iterator j = i - 1;
            while (j != pos)
               *i- = *j-;
         }
         *finish++ = val;
         return pos;
      }
};
To enable the container, we add the following two lines to our gSOAP header file:

#include "simpleVector.h"
template  < class T > class simpleVector;

The container class should not be defined in the gSOAP header file. It must be defined in a separate header file (e.g. "simpleVector.h"). The template  < class T > class simpleVector declaration ensures that gSOAP will recognize simpleVector as a container class.
Caution: when parsing XML content the container elements may not be stored in the same order given in the XML content. When gSOAP parses XML it uses the insert container methods to store elements one by one. However, element content that is "forwarded" with href attributes will be appended to the container. Forwarding can take place with multi-referenced data that is referred to from the main part of the SOAP 1.1 XML message to the independent elements that carry ids. Therefore, your application should not rely on the preservation of the order of elements in a container.

10.11.9  Polymorphic Dynamic Arrays and Lists

Polymorphic arrays (arrays of polymorphic element types) can be encoded when declared as an array of pointers to class instances. and lists. For example:

class ns__Object
{
   public:
   ...
};
class ns__Data: public ns__Object
{
   public:
   ...
};
class ArrayOfObject
{
   public:
   ns__Object **__ptr; // pointer to array of pointers to Objects
   int __size; // number of Objects pointed to
   int __offset; // optional SOAP 1.1 array offset
};

The pointers in the array can point to the ns__Object base class or ns__Data derived class instances which will be serialized and deserialized accordingly in SOAP. That is, the array elements are polymorphic.

10.11.10  How to Change the Tag Names of the Elements of a SOAP Array or List

The __ptr field in a struct or class declaration of a dynamic array may have an optional suffix part that describes the name of the tags of the SOAP array XML elements. The suffix is part of the field name:

Type *__ptrarray_elt_name

The suffix describes the tag name to be used for all array elements. The usual identifier to XML translations apply, see Section 9.3. The default XML element tag name for array elements is item (which corresponds to the use of field name __ptritem).
Consider for example:

struct ArrayOfstring
{
   xsd__string *__ptrstring;    int __size; };

The array is serialized as:

<array xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:string[2]»
<string xsi:type="xsd:string»Hello</string>
<string xsi:type="xsd:string»World</string>
</array>

SOAP 1.1 and 1.2 do not require the use of a specific tag name for array elements. gSOAP will deserialize a SOAP array while ignoring the tag names. Certain XML Schemas used in doc/literal encoding may require the declaration of array element tag names.

10.12  Base64Binary XML Schema Type Encoding

The base64Binary XML Schema type is a special form of dynamic array declared with a pointer (__ptr) to an unsigned char array.
For example using a struct:

struct xsd__base64Binary
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.
The SOAP_ENC:base64 encoding is another type for base 64 binary encoding specified by the SOAP data type schema and some SOAP applications may use this form (as indicated by their WSDL descriptions). It is declared by:

struct SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate SOAP-ENC:base64 serializers and deserializers.
The advantage of using a class is that methods can be used to initialize and manipulate the __ptr and __size fields. The user can add methods to this class to do this. For example:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
   xsd__base64Binary(); // Constructor
   xsd__base64Binary(struct soap *soap, int n); // Constructor
   ~xsd__base64Binary(); // Destructor
   unsigned char *location(); // returns the memory location
   int size(); // returns the number of bytes
};

Here are example method implementations:

xsd__base64Binary::xsd__base64Binary()
{
   __ptr = NULL;
   __size = 0;
}
xsd__base64Binary::xsd__base64Binary(struct soap *soap, int n)
{
   __ptr = (unsigned char*)soap_malloc(soap, n);
   __size = n;
}
xsd__base64Binary::~xsd__base64Binary()
{ }
unsigned char *xsd__base64Binary::location()
{
   return __ptr;
}
int xsd__base64Binary::size()
{
   return __size;
}

The following example in C/C++ reads from a raw image file and encodes the image in SOAP using the base64Binary type:

...
FILE *fd = fopen("image.jpg", "rb");
xsd__base64Binary image(&soap, filesize(fd));
fread(image.location(), image.size(), 1, fd);
fclose(fd);
soap_begin(&soap);
image.soap_serialize(&soap);
image.soap_put(&soap, "jpegimage", NULL);
soap_end(&soap);
...

where filesize is a function that returns the size of a file given a file descriptor.
Reading the xsd:base64Binary encoded image.

...
xsd__base64Binary image;
soap_begin(&soap);
image.get(&soap, "jpegimage");
soap_end(&soap);
...

The struct or class name soap_enc__base64 should be used for SOAP-ENC:base64 schema type instead of xsd__base64Binary.

10.13  hexBinary XML Schema Type Encoding

The hexBinary XML Schema type is a special form of dynamic array declared with the name xsd__hexBinary and a pointer (__ptr) to an unsigned char array.
For example, using a struct:

struct xsd__hexBinary
{
   unsigned char *__ptr;
   int __size;
};

Or using a class:

class xsd__hexBinary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.

10.14  Literal XML Encoding Style

gSOAP supports document/literal encoding by default. Just as with SOAP RPC encoding, literal encoding requires the XML Schema of the message data to be provided e.g. in WSDL in order for the gSOAP compiler to generate the (de)serialization routines. Alternatively, the optional DOM parser (dom.c and dom++.cpp) can be used to handle generic XML or arbitrary XML documents can be (de)serialized into regular C strings or wide character strings (wchar_t*) by gSOAP (see Section 10.14.1).
The //gsoap service encoding, //gsoap service method-encoding, and //gsoap service method-response-encoding directives explicitly enable SOAP encoded or literal encoded messages. For example, to enable RPC encoding style for the entire service, use:

//gsoap ns service encoding: encoded

To enable encoding for particular service methods, use:

//gsoap ns service method-encoding: myMethod encoded
int ns__myMethod(...)

To enable encoding for particular service methods responses when the method request is literal, use:

//gsoap ns service method-response-encoding: myMethod encoded
int ns__myMethod(...)

Instead of the encoded value, you can use literal, or a specific encoding style value.
Consider the following example that uses the directive to make the literal encoding explicit
   typedef pointer iterator;
   typedef const_pointer const_iterator;
protected:
   iterator start;
   iterator finish;
   size_t length;
public:
   simpleVector() { clear(); }
   ~simpleVector() { delete[] start; }
   void\ clear() { start = finish = NULL; }
   iterator begin() { return start; }
   const_iterator begin() const\ { return start; }
   iterator end() { return finish; }
   const_iterator end() const\ { return finish; }
   size_t size() const\ { return finish-start; }
   iterator insert(iterator pos, const_reference val)
      {
         if (!start)
            start = finish = new value_type[length = 4];
         else if (finish > = start + length)
         {
            iterator i = start;
            iterator j = new value_type[2 * length];
            start = j;
            finish = start + length;
            length *= 2;
            if (pos)
               pos = j + (pos - i);
            while (i != finish)
               *j++ = *i++;
         }
         if (pos && pos != finish)
         { iterator i = finish;
            iterator j = i - 1;
            while (j != pos)
               *i- = *j-;
         }
         *finish++ = val;
         return pos;
      }
};
To enable the container, we add the following two lines to our gSOAP header file:

#include "simpleVector.h"
template  < class T > class simpleVector;

The container class should not be defined in the gSOAP header file. It must be defined in a separate header file (e.g. "simpleVector.h"). The template  < class T > class simpleVector declaration ensures that gSOAP will recognize simpleVector as a container class.
Caution: when parsing XML content the container elements may not be stored in the same order given in the XML content. When gSOAP parses XML it uses the insert container methods to store elements one by one. However, element content that is "forwarded" with href attributes will be appended to the container. Forwarding can take place with multi-referenced data that is referred to from the main part of the SOAP 1.1 XML message to the independent elements that carry ids. Therefore, your application should not rely on the preservation of the order of elements in a container.

10.11.9  Polymorphic Dynamic Arrays and Lists

Polymorphic arrays (arrays of polymorphic element types) can be encoded when declared as an array of pointers to class instances. and lists. For example:

class ns__Object
{
   public:
   ...
};
class ns__Data: public ns__Object
{
   public:
   ...
};
class ArrayOfObject
{
   public:
   ns__Object **__ptr; // pointer to array of pointers to Objects
   int __size; // number of Objects pointed to
   int __offset; // optional SOAP 1.1 array offset
};

The pointers in the array can point to the ns__Object base class or ns__Data derived class instances which will be serialized and deserialized accordingly in SOAP. That is, the array elements are polymorphic.

10.11.10  How to Change the Tag Names of the Elements of a SOAP Array or List

The __ptr field in a struct or class declaration of a dynamic array may have an optional suffix part that describes the name of the tags of the SOAP array XML elements. The suffix is part of the field name:

Type *__ptrarray_elt_name

The suffix describes the tag name to be used for all array elements. The usual identifier to XML translations apply, see Section 9.3. The default XML element tag name for array elements is item (which corresponds to the use of field name __ptritem).
Consider for example:

struct ArrayOfstring
{
   xsd__string *__ptrstring;    int __size; };

The array is serialized as:

<array xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:string[2]»
<string xsi:type="xsd:string»Hello</string>
<string xsi:type="xsd:string»World</string>
</array>

SOAP 1.1 and 1.2 do not require the use of a specific tag name for array elements. gSOAP will deserialize a SOAP array while ignoring the tag names. Certain XML Schemas used in doc/literal encoding may require the declaration of array element tag names.

10.12  Base64Binary XML Schema Type Encoding

The base64Binary XML Schema type is a special form of dynamic array declared with a pointer (__ptr) to an unsigned char array.
For example using a struct:

struct xsd__base64Binary
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.
The SOAP_ENC:base64 encoding is another type for base 64 binary encoding specified by the SOAP data type schema and some SOAP applications may use this form (as indicated by their WSDL descriptions). It is declared by:

struct SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate SOAP-ENC:base64 serializers and deserializers.
The advantage of using a class is that methods can be used to initialize and manipulate the __ptr and __size fields. The user can add methods to this class to do this. For example:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
   xsd__base64Binary(); // Constructor
   xsd__base64Binary(struct soap *soap, int n); // Constructor
   ~xsd__base64Binary(); // Destructor
   unsigned char *location(); // returns the memory location
   int size(); // returns the number of bytes
};

Here are example method implementations:

xsd__base64Binary::xsd__base64Binary()
{
   __ptr = NULL;
   __size = 0;
}
xsd__base64Binary::xsd__base64Binary(struct soap *soap, int n)
{
   __ptr = (unsigned char*)soap_malloc(soap, n);
   __size = n;
}
xsd__base64Binary::~xsd__base64Binary()
{ }
unsigned char *xsd__base64Binary::location()
{
   return __ptr;
}
int xsd__base64Binary::size()
{
   return __size;
}

The following example in C/C++ reads from a raw image file and encodes the image in SOAP using the base64Binary type:

...
FILE *fd = fopen("image.jpg", "rb");
xsd__base64Binary image(&soap, filesize(fd));
fread(image.location(), image.size(), 1, fd);
fclose(fd);
soap_begin(&soap);
image.soap_serialize(&soap);
image.soap_put(&soap, "jpegimage", NULL);
soap_end(&soap);
...

where filesize is a function that returns the size of a file given a file descriptor.
Reading the xsd:base64Binary encoded image.

...
xsd__base64Binary image;
soap_begin(&soap);
image.get(&soap, "jpegimage");
soap_end(&soap);
...

The struct or class name soap_enc__base64 should be used for SOAP-ENC:base64 schema type instead of xsd__base64Binary.

10.13  hexBinary XML Schema Type Encoding

The hexBinary XML Schema type is a special form of dynamic array declared with the name xsd__hexBinary and a pointer (__ptr) to an unsigned char array.
For example, using a struct:

struct xsd__hexBinary
{
   unsigned char *__ptr;
   int __size;
};

Or using a class:

class xsd__hexBinary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.

10.14  Literal XML Encoding Style

gSOAP supports document/literal encoding by default. Just as with SOAP RPC encoding, literal encoding requires the XML Schema of the message data to be provided e.g. in WSDL in order for the gSOAP compiler to generate the (de)serialization routines. Alternatively, the optional DOM parser (dom.c and dom++.cpp) can be used to handle generic XML or arbitrary XML documents can be (de)serialized into regular C strings or wide character strings (wchar_t*) by gSOAP (see Section 10.14.1).
The //gsoap service encoding, //gsoap service method-encoding, and //gsoap service method-response-encoding directives explicitly enable SOAP encoded or literal encoded messages. For example, to enable RPC encoding style for the entire service, use:

//gsoap ns service encoding: encoded

To enable encoding for particular service methods, use:

//gsoap ns service method-encoding: myMethod encoded
int ns__myMethod(...)

To enable encoding for particular service methods responses when the method request is literal, use:

//gsoap ns service method-response-encoding: myMethod encoded
int ns__myMethod(...)

Instead of the encoded value, you can use literal, or a specific encoding style value.
Consider the following example that uses the directive to make the literal encoding explicit
   typedef pointer iterator;
   typedef const_pointer const_iterator;
protected:
   iterator start;
   iterator finish;
   size_t length;
public:
   simpleVector() { clear(); }
   ~simpleVector() { delete[] start; }
   void\ clear() { start = finish = NULL; }
   iterator begin() { return start; }
   const_iterator begin() const\ { return start; }
   iterator end() { return finish; }
   const_iterator end() const\ { return finish; }
   size_t size() const\ { return finish-start; }
   iterator insert(iterator pos, const_reference val)
      {
         if (!start)
            start = finish = new value_type[length = 4];
         else if (finish > = start + length)
         {
            iterator i = start;
            iterator j = new value_type[2 * length];
            start = j;
            finish = start + length;
            length *= 2;
            if (pos)
               pos = j + (pos - i);
            while (i != finish)
               *j++ = *i++;
         }
         if (pos && pos != finish)
         { iterator i = finish;
            iterator j = i - 1;
            while (j != pos)
               *i- = *j-;
         }
         *finish++ = val;
         return pos;
      }
};
To enable the container, we add the following two lines to our gSOAP header file:

#include "simpleVector.h"
template  < class T > class simpleVector;

The container class should not be defined in the gSOAP header file. It must be defined in a separate header file (e.g. "simpleVector.h"). The template  < class T > class simpleVector declaration ensures that gSOAP will recognize simpleVector as a container class.
Caution: when parsing XML content the container elements may not be stored in the same order given in the XML content. When gSOAP parses XML it uses the insert container methods to store elements one by one. However, element content that is "forwarded" with href attributes will be appended to the container. Forwarding can take place with multi-referenced data that is referred to from the main part of the SOAP 1.1 XML message to the independent elements that carry ids. Therefore, your application should not rely on the preservation of the order of elements in a container.

10.11.9  Polymorphic Dynamic Arrays and Lists

Polymorphic arrays (arrays of polymorphic element types) can be encoded when declared as an array of pointers to class instances. and lists. For example:

class ns__Object
{
   public:
   ...
};
class ns__Data: public ns__Object
{
   public:
   ...
};
class ArrayOfObject
{
   public:
   ns__Object **__ptr; // pointer to array of pointers to Objects
   int __size; // number of Objects pointed to
   int __offset; // optional SOAP 1.1 array offset
};

The pointers in the array can point to the ns__Object base class or ns__Data derived class instances which will be serialized and deserialized accordingly in SOAP. That is, the array elements are polymorphic.

10.11.10  How to Change the Tag Names of the Elements of a SOAP Array or List

The __ptr field in a struct or class declaration of a dynamic array may have an optional suffix part that describes the name of the tags of the SOAP array XML elements. The suffix is part of the field name:

Type *__ptrarray_elt_name

The suffix describes the tag name to be used for all array elements. The usual identifier to XML translations apply, see Section 9.3. The default XML element tag name for array elements is item (which corresponds to the use of field name __ptritem).
Consider for example:

struct ArrayOfstring
{
   xsd__string *__ptrstring;    int __size; };

The array is serialized as:

<array xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:string[2]»
<string xsi:type="xsd:string»Hello</string>
<string xsi:type="xsd:string»World</string>
</array>

SOAP 1.1 and 1.2 do not require the use of a specific tag name for array elements. gSOAP will deserialize a SOAP array while ignoring the tag names. Certain XML Schemas used in doc/literal encoding may require the declaration of array element tag names.

10.12  Base64Binary XML Schema Type Encoding

The base64Binary XML Schema type is a special form of dynamic array declared with a pointer (__ptr) to an unsigned char array.
For example using a struct:

struct xsd__base64Binary
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.
The SOAP_ENC:base64 encoding is another type for base 64 binary encoding specified by the SOAP data type schema and some SOAP applications may use this form (as indicated by their WSDL descriptions). It is declared by:

struct SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate SOAP-ENC:base64 serializers and deserializers.
The advantage of using a class is that methods can be used to initialize and manipulate the __ptr and __size fields. The user can add methods to this class to do this. For example:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
   xsd__base64Binary(); // Constructor
   xsd__base64Binary(struct soap *soap, int n); // Constructor
   ~xsd__base64Binary(); // Destructor
   unsigned char *location(); // returns the memory location
   int size(); // returns the number of bytes
};

Here are example method implementations:

xsd__base64Binary::xsd__base64Binary()
{
   __ptr = NULL;
   __size = 0;
}
xsd__base64Binary::xsd__base64Binary(struct soap *soap, int n)
{
   __ptr = (unsigned char*)soap_malloc(soap, n);
   __size = n;
}
xsd__base64Binary::~xsd__base64Binary()
{ }
unsigned char *xsd__base64Binary::location()
{
   return __ptr;
}
int xsd__base64Binary::size()
{
   return __size;
}

The following example in C/C++ reads from a raw image file and encodes the image in SOAP using the base64Binary type:

...
FILE *fd = fopen("image.jpg", "rb");
xsd__base64Binary image(&soap, filesize(fd));
fread(image.location(), image.size(), 1, fd);
fclose(fd);
soap_begin(&soap);
image.soap_serialize(&soap);
image.soap_put(&soap, "jpegimage", NULL);
soap_end(&soap);
...

where filesize is a function that returns the size of a file given a file descriptor.
Reading the xsd:base64Binary encoded image.

...
xsd__base64Binary image;
soap_begin(&soap);
image.get(&soap, "jpegimage");
soap_end(&soap);
...

The struct or class name soap_enc__base64 should be used for SOAP-ENC:base64 schema type instead of xsd__base64Binary.

10.13  hexBinary XML Schema Type Encoding

The hexBinary XML Schema type is a special form of dynamic array declared with the name xsd__hexBinary and a pointer (__ptr) to an unsigned char array.
For example, using a struct:

struct xsd__hexBinary
{
   unsigned char *__ptr;
   int __size;
};

Or using a class:

class xsd__hexBinary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.

10.14  Literal XML Encoding Style

gSOAP supports document/literal encoding by default. Just as with SOAP RPC encoding, literal encoding requires the XML Schema of the message data to be provided e.g. in WSDL in order for the gSOAP compiler to generate the (de)serialization routines. Alternatively, the optional DOM parser (dom.c and dom++.cpp) can be used to handle generic XML or arbitrary XML documents can be (de)serialized into regular C strings or wide character strings (wchar_t*) by gSOAP (see Section 10.14.1).
The //gsoap service encoding, //gsoap service method-encoding, and //gsoap service method-response-encoding directives explicitly enable SOAP encoded or literal encoded messages. For example, to enable RPC encoding style for the entire service, use:

//gsoap ns service encoding: encoded

To enable encoding for particular service methods, use:

//gsoap ns service method-encoding: myMethod encoded
int ns__myMethod(...)

To enable encoding for particular service methods responses when the method request is literal, use:

//gsoap ns service method-response-encoding: myMethod encoded
int ns__myMethod(...)

Instead of the encoded value, you can use literal, or a specific encoding style value.
Consider the following example that uses the directive to make the literal encoding explicit
   typedef pointer iterator;
   typedef const_pointer const_iterator;
protected:
   iterator start;
   iterator finish;
   size_t length;
public:
   simpleVector() { clear(); }
   ~simpleVector() { delete[] start; }
   void\ clear() { start = finish = NULL; }
   iterator begin() { return start; }
   const_iterator begin() const\ { return start; }
   iterator end() { return finish; }
   const_iterator end() const\ { return finish; }
   size_t size() const\ { return finish-start; }
   iterator insert(iterator pos, const_reference val)
      {
         if (!start)
            start = finish = new value_type[length = 4];
         else if (finish > = start + length)
         {
            iterator i = start;
            iterator j = new value_type[2 * length];
            start = j;
            finish = start + length;
            length *= 2;
            if (pos)
               pos = j + (pos - i);
            while (i != finish)
               *j++ = *i++;
         }
         if (pos && pos != finish)
         { iterator i = finish;
            iterator j = i - 1;
            while (j != pos)
               *i- = *j-;
         }
         *finish++ = val;
         return pos;
      }
};
To enable the container, we add the following two lines to our gSOAP header file:

#include "simpleVector.h"
template  < class T > class simpleVector;

The container class should not be defined in the gSOAP header file. It must be defined in a separate header file (e.g. "simpleVector.h"). The template  < class T > class simpleVector declaration ensures that gSOAP will recognize simpleVector as a container class.
Caution: when parsing XML content the container elements may not be stored in the same order given in the XML content. When gSOAP parses XML it uses the insert container methods to store elements one by one. However, element content that is "forwarded" with href attributes will be appended to the container. Forwarding can take place with multi-referenced data that is referred to from the main part of the SOAP 1.1 XML message to the independent elements that carry ids. Therefore, your application should not rely on the preservation of the order of elements in a container.

10.11.9  Polymorphic Dynamic Arrays and Lists

Polymorphic arrays (arrays of polymorphic element types) can be encoded when declared as an array of pointers to class instances. and lists. For example:

class ns__Object
{
   public:
   ...
};
class ns__Data: public ns__Object
{
   public:
   ...
};
class ArrayOfObject
{
   public:
   ns__Object **__ptr; // pointer to array of pointers to Objects
   int __size; // number of Objects pointed to
   int __offset; // optional SOAP 1.1 array offset
};

The pointers in the array can point to the ns__Object base class or ns__Data derived class instances which will be serialized and deserialized accordingly in SOAP. That is, the array elements are polymorphic.

10.11.10  How to Change the Tag Names of the Elements of a SOAP Array or List

The __ptr field in a struct or class declaration of a dynamic array may have an optional suffix part that describes the name of the tags of the SOAP array XML elements. The suffix is part of the field name:

Type *__ptrarray_elt_name

The suffix describes the tag name to be used for all array elements. The usual identifier to XML translations apply, see Section 9.3. The default XML element tag name for array elements is item (which corresponds to the use of field name __ptritem).
Consider for example:

struct ArrayOfstring
{
   xsd__string *__ptrstring;    int __size; };

The array is serialized as:

<array xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:string[2]»
<string xsi:type="xsd:string»Hello</string>
<string xsi:type="xsd:string»World</string>
</array>

SOAP 1.1 and 1.2 do not require the use of a specific tag name for array elements. gSOAP will deserialize a SOAP array while ignoring the tag names. Certain XML Schemas used in doc/literal encoding may require the declaration of array element tag names.

10.12  Base64Binary XML Schema Type Encoding

The base64Binary XML Schema type is a special form of dynamic array declared with a pointer (__ptr) to an unsigned char array.
For example using a struct:

struct xsd__base64Binary
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.
The SOAP_ENC:base64 encoding is another type for base 64 binary encoding specified by the SOAP data type schema and some SOAP applications may use this form (as indicated by their WSDL descriptions). It is declared by:

struct SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate SOAP-ENC:base64 serializers and deserializers.
The advantage of using a class is that methods can be used to initialize and manipulate the __ptr and __size fields. The user can add methods to this class to do this. For example:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
   xsd__base64Binary(); // Constructor
   xsd__base64Binary(struct soap *soap, int n); // Constructor
   ~xsd__base64Binary(); // Destructor
   unsigned char *location(); // returns the memory location
   int size(); // returns the number of bytes
};

Here are example method implementations:

xsd__base64Binary::xsd__base64Binary()
{
   __ptr = NULL;
   __size = 0;
}
xsd__base64Binary::xsd__base64Binary(struct soap *soap, int n)
{
   __ptr = (unsigned char*)soap_malloc(soap, n);
   __size = n;
}
xsd__base64Binary::~xsd__base64Binary()
{ }
unsigned char *xsd__base64Binary::location()
{
   return __ptr;
}
int xsd__base64Binary::size()
{
   return __size;
}

The following example in C/C++ reads from a raw image file and encodes the image in SOAP using the base64Binary type:

...
FILE *fd = fopen("image.jpg", "rb");
xsd__base64Binary image(&soap, filesize(fd));
fread(image.location(), image.size(), 1, fd);
fclose(fd);
soap_begin(&soap);
image.soap_serialize(&soap);
image.soap_put(&soap, "jpegimage", NULL);
soap_end(&soap);
...

where filesize is a function that returns the size of a file given a file descriptor.
Reading the xsd:base64Binary encoded image.

...
xsd__base64Binary image;
soap_begin(&soap);
image.get(&soap, "jpegimage");
soap_end(&soap);
...

The struct or class name soap_enc__base64 should be used for SOAP-ENC:base64 schema type instead of xsd__base64Binary.

10.13  hexBinary XML Schema Type Encoding

The hexBinary XML Schema type is a special form of dynamic array declared with the name xsd__hexBinary and a pointer (__ptr) to an unsigned char array.
For example, using a struct:

struct xsd__hexBinary
{
   unsigned char *__ptr;
   int __size;
};

Or using a class:

class xsd__hexBinary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.

10.14  Literal XML Encoding Style

gSOAP supports document/literal encoding by default. Just as with SOAP RPC encoding, literal encoding requires the XML Schema of the message data to be provided e.g. in WSDL in order for the gSOAP compiler to generate the (de)serialization routines. Alternatively, the optional DOM parser (dom.c and dom++.cpp) can be used to handle generic XML or arbitrary XML documents can be (de)serialized into regular C strings or wide character strings (wchar_t*) by gSOAP (see Section 10.14.1).
The //gsoap service encoding, //gsoap service method-encoding, and //gsoap service method-response-encoding directives explicitly enable SOAP encoded or literal encoded messages. For example, to enable RPC encoding style for the entire service, use:

//gsoap ns service encoding: encoded

To enable encoding for particular service methods, use:

//gsoap ns service method-encoding: myMethod encoded
int ns__myMethod(...)

To enable encoding for particular service methods responses when the method request is literal, use:

//gsoap ns service method-response-encoding: myMethod encoded
int ns__myMethod(...)

Instead of the encoded value, you can use literal, or a specific encoding style value.
Consider the following example that uses the directive to make the literal encoding explicit
   typedef pointer iterator;
   typedef const_pointer const_iterator;
protected:
   iterator start;
   iterator finish;
   size_t length;
public:
   simpleVector() { clear(); }
   ~simpleVector() { delete[] start; }
   void\ clear() { start = finish = NULL; }
   iterator begin() { return start; }
   const_iterator begin() const\ { return start; }
   iterator end() { return finish; }
   const_iterator end() const\ { return finish; }
   size_t size() const\ { return finish-start; }
   iterator insert(iterator pos, const_reference val)
      {
         if (!start)
            start = finish = new value_type[length = 4];
         else if (finish > = start + length)
         {
            iterator i = start;
            iterator j = new value_type[2 * length];
            start = j;
            finish = start + length;
            length *= 2;
            if (pos)
               pos = j + (pos - i);
            while (i != finish)
               *j++ = *i++;
         }
         if (pos && pos != finish)
         { iterator i = finish;
            iterator j = i - 1;
            while (j != pos)
               *i- = *j-;
         }
         *finish++ = val;
         return pos;
      }
};
To enable the container, we add the following two lines to our gSOAP header file:

#include "simpleVector.h"
template  < class T > class simpleVector;

The container class should not be defined in the gSOAP header file. It must be defined in a separate header file (e.g. "simpleVector.h"). The template  < class T > class simpleVector declaration ensures that gSOAP will recognize simpleVector as a container class.
Caution: when parsing XML content the container elements may not be stored in the same order given in the XML content. When gSOAP parses XML it uses the insert container methods to store elements one by one. However, element content that is "forwarded" with href attributes will be appended to the container. Forwarding can take place with multi-referenced data that is referred to from the main part of the SOAP 1.1 XML message to the independent elements that carry ids. Therefore, your application should not rely on the preservation of the order of elements in a container.

10.11.9  Polymorphic Dynamic Arrays and Lists

Polymorphic arrays (arrays of polymorphic element types) can be encoded when declared as an array of pointers to class instances. and lists. For example:

class ns__Object
{
   public:
   ...
};
class ns__Data: public ns__Object
{
   public:
   ...
};
class ArrayOfObject
{
   public:
   ns__Object **__ptr; // pointer to array of pointers to Objects
   int __size; // number of Objects pointed to
   int __offset; // optional SOAP 1.1 array offset
};

The pointers in the array can point to the ns__Object base class or ns__Data derived class instances which will be serialized and deserialized accordingly in SOAP. That is, the array elements are polymorphic.

10.11.10  How to Change the Tag Names of the Elements of a SOAP Array or List

The __ptr field in a struct or class declaration of a dynamic array may have an optional suffix part that describes the name of the tags of the SOAP array XML elements. The suffix is part of the field name:

Type *__ptrarray_elt_name

The suffix describes the tag name to be used for all array elements. The usual identifier to XML translations apply, see Section 9.3. The default XML element tag name for array elements is item (which corresponds to the use of field name __ptritem).
Consider for example:

struct ArrayOfstring
{
   xsd__string *__ptrstring;    int __size; };

The array is serialized as:

<array xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:string[2]»
<string xsi:type="xsd:string»Hello</string>
<string xsi:type="xsd:string»World</string>
</array>

SOAP 1.1 and 1.2 do not require the use of a specific tag name for array elements. gSOAP will deserialize a SOAP array while ignoring the tag names. Certain XML Schemas used in doc/literal encoding may require the declaration of array element tag names.

10.12  Base64Binary XML Schema Type Encoding

The base64Binary XML Schema type is a special form of dynamic array declared with a pointer (__ptr) to an unsigned char array.
For example using a struct:

struct xsd__base64Binary
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.
The SOAP_ENC:base64 encoding is another type for base 64 binary encoding specified by the SOAP data type schema and some SOAP applications may use this form (as indicated by their WSDL descriptions). It is declared by:

struct SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate SOAP-ENC:base64 serializers and deserializers.
The advantage of using a class is that methods can be used to initialize and manipulate the __ptr and __size fields. The user can add methods to this class to do this. For example:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
   xsd__base64Binary(); // Constructor
   xsd__base64Binary(struct soap *soap, int n); // Constructor
   ~xsd__base64Binary(); // Destructor
   unsigned char *location(); // returns the memory location
   int size(); // returns the number of bytes
};

Here are example method implementations:

xsd__base64Binary::xsd__base64Binary()
{
   __ptr = NULL;
   __size = 0;
}
xsd__base64Binary::xsd__base64Binary(struct soap *soap, int n)
{
   __ptr = (unsigned char*)soap_malloc(soap, n);
   __size = n;
}
xsd__base64Binary::~xsd__base64Binary()
{ }
unsigned char *xsd__base64Binary::location()
{
   return __ptr;
}
int xsd__base64Binary::size()
{
   return __size;
}

The following example in C/C++ reads from a raw image file and encodes the image in SOAP using the base64Binary type:

...
FILE *fd = fopen("image.jpg", "rb");
xsd__base64Binary image(&soap, filesize(fd));
fread(image.location(), image.size(), 1, fd);
fclose(fd);
soap_begin(&soap);
image.soap_serialize(&soap);
image.soap_put(&soap, "jpegimage", NULL);
soap_end(&soap);
...

where filesize is a function that returns the size of a file given a file descriptor.
Reading the xsd:base64Binary encoded image.

...
xsd__base64Binary image;
soap_begin(&soap);
image.get(&soap, "jpegimage");
soap_end(&soap);
...

The struct or class name soap_enc__base64 should be used for SOAP-ENC:base64 schema type instead of xsd__base64Binary.

10.13  hexBinary XML Schema Type Encoding

The hexBinary XML Schema type is a special form of dynamic array declared with the name xsd__hexBinary and a pointer (__ptr) to an unsigned char array.
For example, using a struct:

struct xsd__hexBinary
{
   unsigned char *__ptr;
   int __size;
};

Or using a class:

class xsd__hexBinary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.

10.14  Literal XML Encoding Style

gSOAP supports document/literal encoding by default. Just as with SOAP RPC encoding, literal encoding requires the XML Schema of the message data to be provided e.g. in WSDL in order for the gSOAP compiler to generate the (de)serialization routines. Alternatively, the optional DOM parser (dom.c and dom++.cpp) can be used to handle generic XML or arbitrary XML documents can be (de)serialized into regular C strings or wide character strings (wchar_t*) by gSOAP (see Section 10.14.1).
The //gsoap service encoding, //gsoap service method-encoding, and //gsoap service method-response-encoding directives explicitly enable SOAP encoded or literal encoded messages. For example, to enable RPC encoding style for the entire service, use:

//gsoap ns service encoding: encoded

To enable encoding for particular service methods, use:

//gsoap ns service method-encoding: myMethod encoded
int ns__myMethod(...)

To enable encoding for particular service methods responses when the method request is literal, use:

//gsoap ns service method-response-encoding: myMethod encoded
int ns__myMethod(...)

Instead of the encoded value, you can use literal, or a specific encoding style value.
Consider the following example that uses the directive to make the literal encoding explicit
   typedef pointer iterator;
   typedef const_pointer const_iterator;
protected:
   iterator start;
   iterator finish;
   size_t length;
public:
   simpleVector() { clear(); }
   ~simpleVector() { delete[] start; }
   void\ clear() { start = finish = NULL; }
   iterator begin() { return start; }
   const_iterator begin() const\ { return start; }
   iterator end() { return finish; }
   const_iterator end() const\ { return finish; }
   size_t size() const\ { return finish-start; }
   iterator insert(iterator pos, const_reference val)
      {
         if (!start)
            start = finish = new value_type[length = 4];
         else if (finish > = start + length)
         {
            iterator i = start;
            iterator j = new value_type[2 * length];
            start = j;
            finish = start + length;
            length *= 2;
            if (pos)
               pos = j + (pos - i);
            while (i != finish)
               *j++ = *i++;
         }
         if (pos && pos != finish)
         { iterator i = finish;
            iterator j = i - 1;
            while (j != pos)
               *i- = *j-;
         }
         *finish++ = val;
         return pos;
      }
};
To enable the container, we add the following two lines to our gSOAP header file:

#include "simpleVector.h"
template  < class T > class simpleVector;

The container class should not be defined in the gSOAP header file. It must be defined in a separate header file (e.g. "simpleVector.h"). The template  < class T > class simpleVector declaration ensures that gSOAP will recognize simpleVector as a container class.
Caution: when parsing XML content the container elements may not be stored in the same order given in the XML content. When gSOAP parses XML it uses the insert container methods to store elements one by one. However, element content that is "forwarded" with href attributes will be appended to the container. Forwarding can take place with multi-referenced data that is referred to from the main part of the SOAP 1.1 XML message to the independent elements that carry ids. Therefore, your application should not rely on the preservation of the order of elements in a container.

10.11.9  Polymorphic Dynamic Arrays and Lists

Polymorphic arrays (arrays of polymorphic element types) can be encoded when declared as an array of pointers to class instances. and lists. For example:

class ns__Object
{
   public:
   ...
};
class ns__Data: public ns__Object
{
   public:
   ...
};
class ArrayOfObject
{
   public:
   ns__Object **__ptr; // pointer to array of pointers to Objects
   int __size; // number of Objects pointed to
   int __offset; // optional SOAP 1.1 array offset
};

The pointers in the array can point to the ns__Object base class or ns__Data derived class instances which will be serialized and deserialized accordingly in SOAP. That is, the array elements are polymorphic.

10.11.10  How to Change the Tag Names of the Elements of a SOAP Array or List

The __ptr field in a struct or class declaration of a dynamic array may have an optional suffix part that describes the name of the tags of the SOAP array XML elements. The suffix is part of the field name:

Type *__ptrarray_elt_name

The suffix describes the tag name to be used for all array elements. The usual identifier to XML translations apply, see Section 9.3. The default XML element tag name for array elements is item (which corresponds to the use of field name __ptritem).
Consider for example:

struct ArrayOfstring
{
   xsd__string *__ptrstring;    int __size; };

The array is serialized as:

<array xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:string[2]»
<string xsi:type="xsd:string»Hello</string>
<string xsi:type="xsd:string»World</string>
</array>

SOAP 1.1 and 1.2 do not require the use of a specific tag name for array elements. gSOAP will deserialize a SOAP array while ignoring the tag names. Certain XML Schemas used in doc/literal encoding may require the declaration of array element tag names.

10.12  Base64Binary XML Schema Type Encoding

The base64Binary XML Schema type is a special form of dynamic array declared with a pointer (__ptr) to an unsigned char array.
For example using a struct:

struct xsd__base64Binary
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.
The SOAP_ENC:base64 encoding is another type for base 64 binary encoding specified by the SOAP data type schema and some SOAP applications may use this form (as indicated by their WSDL descriptions). It is declared by:

struct SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate SOAP-ENC:base64 serializers and deserializers.
The advantage of using a class is that methods can be used to initialize and manipulate the __ptr and __size fields. The user can add methods to this class to do this. For example:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
   xsd__base64Binary(); // Constructor
   xsd__base64Binary(struct soap *soap, int n); // Constructor
   ~xsd__base64Binary(); // Destructor
   unsigned char *location(); // returns the memory location
   int size(); // returns the number of bytes
};

Here are example method implementations:

xsd__base64Binary::xsd__base64Binary()
{
   __ptr = NULL;
   __size = 0;
}
xsd__base64Binary::xsd__base64Binary(struct soap *soap, int n)
{
   __ptr = (unsigned char*)soap_malloc(soap, n);
   __size = n;
}
xsd__base64Binary::~xsd__base64Binary()
{ }
unsigned char *xsd__base64Binary::location()
{
   return __ptr;
}
int xsd__base64Binary::size()
{
   return __size;
}

The following example in C/C++ reads from a raw image file and encodes the image in SOAP using the base64Binary type:

...
FILE *fd = fopen("image.jpg", "rb");
xsd__base64Binary image(&soap, filesize(fd));
fread(image.location(), image.size(), 1, fd);
fclose(fd);
soap_begin(&soap);
image.soap_serialize(&soap);
image.soap_put(&soap, "jpegimage", NULL);
soap_end(&soap);
...

where filesize is a function that returns the size of a file given a file descriptor.
Reading the xsd:base64Binary encoded image.

...
xsd__base64Binary image;
soap_begin(&soap);
image.get(&soap, "jpegimage");
soap_end(&soap);
...

The struct or class name soap_enc__base64 should be used for SOAP-ENC:base64 schema type instead of xsd__base64Binary.

10.13  hexBinary XML Schema Type Encoding

The hexBinary XML Schema type is a special form of dynamic array declared with the name xsd__hexBinary and a pointer (__ptr) to an unsigned char array.
For example, using a struct:

struct xsd__hexBinary
{
   unsigned char *__ptr;
   int __size;
};

Or using a class:

class xsd__hexBinary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.

10.14  Literal XML Encoding Style

gSOAP supports document/literal encoding by default. Just as with SOAP RPC encoding, literal encoding requires the XML Schema of the message data to be provided e.g. in WSDL in order for the gSOAP compiler to generate the (de)serialization routines. Alternatively, the optional DOM parser (dom.c and dom++.cpp) can be used to handle generic XML or arbitrary XML documents can be (de)serialized into regular C strings or wide character strings (wchar_t*) by gSOAP (see Section 10.14.1).
The //gsoap service encoding, //gsoap service method-encoding, and //gsoap service method-response-encoding directives explicitly enable SOAP encoded or literal encoded messages. For example, to enable RPC encoding style for the entire service, use:

//gsoap ns service encoding: encoded

To enable encoding for particular service methods, use:

//gsoap ns service method-encoding: myMethod encoded
int ns__myMethod(...)

To enable encoding for particular service methods responses when the method request is literal, use:

//gsoap ns service method-response-encoding: myMethod encoded
int ns__myMethod(...)

Instead of the encoded value, you can use literal, or a specific encoding style value.
Consider the following example that uses the directive to make the literal encoding explicit
   typedef pointer iterator;
   typedef const_pointer const_iterator;
protected:
   iterator start;
   iterator finish;
   size_t length;
public:
   simpleVector() { clear(); }
   ~simpleVector() { delete[] start; }
   void\ clear() { start = finish = NULL; }
   iterator begin() { return start; }
   const_iterator begin() const\ { return start; }
   iterator end() { return finish; }
   const_iterator end() const\ { return finish; }
   size_t size() const\ { return finish-start; }
   iterator insert(iterator pos, const_reference val)
      {
         if (!start)
            start = finish = new value_type[length = 4];
         else if (finish > = start + length)
         {
            iterator i = start;
            iterator j = new value_type[2 * length];
            start = j;
            finish = start + length;
            length *= 2;
            if (pos)
               pos = j + (pos - i);
            while (i != finish)
               *j++ = *i++;
         }
         if (pos && pos != finish)
         { iterator i = finish;
            iterator j = i - 1;
            while (j != pos)
               *i- = *j-;
         }
         *finish++ = val;
         return pos;
      }
};
To enable the container, we add the following two lines to our gSOAP header file:

#include "simpleVector.h"
template  < class T > class simpleVector;

The container class should not be defined in the gSOAP header file. It must be defined in a separate header file (e.g. "simpleVector.h"). The template  < class T > class simpleVector declaration ensures that gSOAP will recognize simpleVector as a container class.
Caution: when parsing XML content the container elements may not be stored in the same order given in the XML content. When gSOAP parses XML it uses the insert container methods to store elements one by one. However, element content that is "forwarded" with href attributes will be appended to the container. Forwarding can take place with multi-referenced data that is referred to from the main part of the SOAP 1.1 XML message to the independent elements that carry ids. Therefore, your application should not rely on the preservation of the order of elements in a container.

10.11.9  Polymorphic Dynamic Arrays and Lists

Polymorphic arrays (arrays of polymorphic element types) can be encoded when declared as an array of pointers to class instances. and lists. For example:

class ns__Object
{
   public:
   ...
};
class ns__Data: public ns__Object
{
   public:
   ...
};
class ArrayOfObject
{
   public:
   ns__Object **__ptr; // pointer to array of pointers to Objects
   int __size; // number of Objects pointed to
   int __offset; // optional SOAP 1.1 array offset
};

The pointers in the array can point to the ns__Object base class or ns__Data derived class instances which will be serialized and deserialized accordingly in SOAP. That is, the array elements are polymorphic.

10.11.10  How to Change the Tag Names of the Elements of a SOAP Array or List

The __ptr field in a struct or class declaration of a dynamic array may have an optional suffix part that describes the name of the tags of the SOAP array XML elements. The suffix is part of the field name:

Type *__ptrarray_elt_name

The suffix describes the tag name to be used for all array elements. The usual identifier to XML translations apply, see Section 9.3. The default XML element tag name for array elements is item (which corresponds to the use of field name __ptritem).
Consider for example:

struct ArrayOfstring
{
   xsd__string *__ptrstring;    int __size; };

The array is serialized as:

<array xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:string[2]»
<string xsi:type="xsd:string»Hello</string>
<string xsi:type="xsd:string»World</string>
</array>

SOAP 1.1 and 1.2 do not require the use of a specific tag name for array elements. gSOAP will deserialize a SOAP array while ignoring the tag names. Certain XML Schemas used in doc/literal encoding may require the declaration of array element tag names.

10.12  Base64Binary XML Schema Type Encoding

The base64Binary XML Schema type is a special form of dynamic array declared with a pointer (__ptr) to an unsigned char array.
For example using a struct:

struct xsd__base64Binary
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.
The SOAP_ENC:base64 encoding is another type for base 64 binary encoding specified by the SOAP data type schema and some SOAP applications may use this form (as indicated by their WSDL descriptions). It is declared by:

struct SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate SOAP-ENC:base64 serializers and deserializers.
The advantage of using a class is that methods can be used to initialize and manipulate the __ptr and __size fields. The user can add methods to this class to do this. For example:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
   xsd__base64Binary(); // Constructor
   xsd__base64Binary(struct soap *soap, int n); // Constructor
   ~xsd__base64Binary(); // Destructor
   unsigned char *location(); // returns the memory location
   int size(); // returns the number of bytes
};

Here are example method implementations:

xsd__base64Binary::xsd__base64Binary()
{
   __ptr = NULL;
   __size = 0;
}
xsd__base64Binary::xsd__base64Binary(struct soap *soap, int n)
{
   __ptr = (unsigned char*)soap_malloc(soap, n);
   __size = n;
}
xsd__base64Binary::~xsd__base64Binary()
{ }
unsigned char *xsd__base64Binary::location()
{
   return __ptr;
}
int xsd__base64Binary::size()
{
   return __size;
}

The following example in C/C++ reads from a raw image file and encodes the image in SOAP using the base64Binary type:

...
FILE *fd = fopen("image.jpg", "rb");
xsd__base64Binary image(&soap, filesize(fd));
fread(image.location(), image.size(), 1, fd);
fclose(fd);
soap_begin(&soap);
image.soap_serialize(&soap);
image.soap_put(&soap, "jpegimage", NULL);
soap_end(&soap);
...

where filesize is a function that returns the size of a file given a file descriptor.
Reading the xsd:base64Binary encoded image.

...
xsd__base64Binary image;
soap_begin(&soap);
image.get(&soap, "jpegimage");
soap_end(&soap);
...

The struct or class name soap_enc__base64 should be used for SOAP-ENC:base64 schema type instead of xsd__base64Binary.

10.13  hexBinary XML Schema Type Encoding

The hexBinary XML Schema type is a special form of dynamic array declared with the name xsd__hexBinary and a pointer (__ptr) to an unsigned char array.
For example, using a struct:

struct xsd__hexBinary
{
   unsigned char *__ptr;
   int __size;
};

Or using a class:

class xsd__hexBinary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.

10.14  Literal XML Encoding Style

gSOAP supports document/literal encoding by default. Just as with SOAP RPC encoding, literal encoding requires the XML Schema of the message data to be provided e.g. in WSDL in order for the gSOAP compiler to generate the (de)serialization routines. Alternatively, the optional DOM parser (dom.c and dom++.cpp) can be used to handle generic XML or arbitrary XML documents can be (de)serialized into regular C strings or wide character strings (wchar_t*) by gSOAP (see Section 10.14.1).
The //gsoap service encoding, //gsoap service method-encoding, and //gsoap service method-response-encoding directives explicitly enable SOAP encoded or literal encoded messages. For example, to enable RPC encoding style for the entire service, use:

//gsoap ns service encoding: encoded

To enable encoding for particular service methods, use:

//gsoap ns service method-encoding: myMethod encoded
int ns__myMethod(...)

To enable encoding for particular service methods responses when the method request is literal, use:

//gsoap ns service method-response-encoding: myMethod encoded
int ns__myMethod(...)

Instead of the encoded value, you can use literal, or a specific encoding style value.
Consider the following example that uses the directive to make the literal encoding explicit
   typedef pointer iterator;
   typedef const_pointer const_iterator;
protected:
   iterator start;
   iterator finish;
   size_t length;
public:
   simpleVector() { clear(); }
   ~simpleVector() { delete[] start; }
   void\ clear() { start = finish = NULL; }
   iterator begin() { return start; }
   const_iterator begin() const\ { return start; }
   iterator end() { return finish; }
   const_iterator end() const\ { return finish; }
   size_t size() const\ { return finish-start; }
   iterator insert(iterator pos, const_reference val)
      {
         if (!start)
            start = finish = new value_type[length = 4];
         else if (finish > = start + length)
         {
            iterator i = start;
            iterator j = new value_type[2 * length];
            start = j;
            finish = start + length;
            length *= 2;
            if (pos)
               pos = j + (pos - i);
            while (i != finish)
               *j++ = *i++;
         }
         if (pos && pos != finish)
         { iterator i = finish;
            iterator j = i - 1;
            while (j != pos)
               *i- = *j-;
         }
         *finish++ = val;
         return pos;
      }
};
To enable the container, we add the following two lines to our gSOAP header file:

#include "simpleVector.h"
template  < class T > class simpleVector;

The container class should not be defined in the gSOAP header file. It must be defined in a separate header file (e.g. "simpleVector.h"). The template  < class T > class simpleVector declaration ensures that gSOAP will recognize simpleVector as a container class.
Caution: when parsing XML content the container elements may not be stored in the same order given in the XML content. When gSOAP parses XML it uses the insert container methods to store elements one by one. However, element content that is "forwarded" with href attributes will be appended to the container. Forwarding can take place with multi-referenced data that is referred to from the main part of the SOAP 1.1 XML message to the independent elements that carry ids. Therefore, your application should not rely on the preservation of the order of elements in a container.

10.11.9  Polymorphic Dynamic Arrays and Lists

Polymorphic arrays (arrays of polymorphic element types) can be encoded when declared as an array of pointers to class instances. and lists. For example:

class ns__Object
{
   public:
   ...
};
class ns__Data: public ns__Object
{
   public:
   ...
};
class ArrayOfObject
{
   public:
   ns__Object **__ptr; // pointer to array of pointers to Objects
   int __size; // number of Objects pointed to
   int __offset; // optional SOAP 1.1 array offset
};

The pointers in the array can point to the ns__Object base class or ns__Data derived class instances which will be serialized and deserialized accordingly in SOAP. That is, the array elements are polymorphic.

10.11.10  How to Change the Tag Names of the Elements of a SOAP Array or List

The __ptr field in a struct or class declaration of a dynamic array may have an optional suffix part that describes the name of the tags of the SOAP array XML elements. The suffix is part of the field name:

Type *__ptrarray_elt_name

The suffix describes the tag name to be used for all array elements. The usual identifier to XML translations apply, see Section 9.3. The default XML element tag name for array elements is item (which corresponds to the use of field name __ptritem).
Consider for example:

struct ArrayOfstring
{
   xsd__string *__ptrstring;    int __size; };

The array is serialized as:

<array xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:string[2]»
<string xsi:type="xsd:string»Hello</string>
<string xsi:type="xsd:string»World</string>
</array>

SOAP 1.1 and 1.2 do not require the use of a specific tag name for array elements. gSOAP will deserialize a SOAP array while ignoring the tag names. Certain XML Schemas used in doc/literal encoding may require the declaration of array element tag names.

10.12  Base64Binary XML Schema Type Encoding

The base64Binary XML Schema type is a special form of dynamic array declared with a pointer (__ptr) to an unsigned char array.
For example using a struct:

struct xsd__base64Binary
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.
The SOAP_ENC:base64 encoding is another type for base 64 binary encoding specified by the SOAP data type schema and some SOAP applications may use this form (as indicated by their WSDL descriptions). It is declared by:

struct SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate SOAP-ENC:base64 serializers and deserializers.
The advantage of using a class is that methods can be used to initialize and manipulate the __ptr and __size fields. The user can add methods to this class to do this. For example:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
   xsd__base64Binary(); // Constructor
   xsd__base64Binary(struct soap *soap, int n); // Constructor
   ~xsd__base64Binary(); // Destructor
   unsigned char *location(); // returns the memory location
   int size(); // returns the number of bytes
};

Here are example method implementations:

xsd__base64Binary::xsd__base64Binary()
{
   __ptr = NULL;
   __size = 0;
}
xsd__base64Binary::xsd__base64Binary(struct soap *soap, int n)
{
   __ptr = (unsigned char*)soap_malloc(soap, n);
   __size = n;
}
xsd__base64Binary::~xsd__base64Binary()
{ }
unsigned char *xsd__base64Binary::location()
{
   return __ptr;
}
int xsd__base64Binary::size()
{
   return __size;
}

The following example in C/C++ reads from a raw image file and encodes the image in SOAP using the base64Binary type:

...
FILE *fd = fopen("image.jpg", "rb");
xsd__base64Binary image(&soap, filesize(fd));
fread(image.location(), image.size(), 1, fd);
fclose(fd);
soap_begin(&soap);
image.soap_serialize(&soap);
image.soap_put(&soap, "jpegimage", NULL);
soap_end(&soap);
...

where filesize is a function that returns the size of a file given a file descriptor.
Reading the xsd:base64Binary encoded image.

...
xsd__base64Binary image;
soap_begin(&soap);
image.get(&soap, "jpegimage");
soap_end(&soap);
...

The struct or class name soap_enc__base64 should be used for SOAP-ENC:base64 schema type instead of xsd__base64Binary.

10.13  hexBinary XML Schema Type Encoding

The hexBinary XML Schema type is a special form of dynamic array declared with the name xsd__hexBinary and a pointer (__ptr) to an unsigned char array.
For example, using a struct:

struct xsd__hexBinary
{
   unsigned char *__ptr;
   int __size;
};

Or using a class:

class xsd__hexBinary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.

10.14  Literal XML Encoding Style

gSOAP supports document/literal encoding by default. Just as with SOAP RPC encoding, literal encoding requires the XML Schema of the message data to be provided e.g. in WSDL in order for the gSOAP compiler to generate the (de)serialization routines. Alternatively, the optional DOM parser (dom.c and dom++.cpp) can be used to handle generic XML or arbitrary XML documents can be (de)serialized into regular C strings or wide character strings (wchar_t*) by gSOAP (see Section 10.14.1).
The //gsoap service encoding, //gsoap service method-encoding, and //gsoap service method-response-encoding directives explicitly enable SOAP encoded or literal encoded messages. For example, to enable RPC encoding style for the entire service, use:

//gsoap ns service encoding: encoded

To enable encoding for particular service methods, use:

//gsoap ns service method-encoding: myMethod encoded
int ns__myMethod(...)

To enable encoding for particular service methods responses when the method request is literal, use:

//gsoap ns service method-response-encoding: myMethod encoded
int ns__myMethod(...)

Instead of the encoded value, you can use literal, or a specific encoding style value.
Consider the following example that uses the directive to make the literal encoding explicit
   typedef pointer iterator;
   typedef const_pointer const_iterator;
protected:
   iterator start;
   iterator finish;
   size_t length;
public:
   simpleVector() { clear(); }
   ~simpleVector() { delete[] start; }
   void\ clear() { start = finish = NULL; }
   iterator begin() { return start; }
   const_iterator begin() const\ { return start; }
   iterator end() { return finish; }
   const_iterator end() const\ { return finish; }
   size_t size() const\ { return finish-start; }
   iterator insert(iterator pos, const_reference val)
      {
         if (!start)
            start = finish = new value_type[length = 4];
         else if (finish > = start + length)
         {
            iterator i = start;
            iterator j = new value_type[2 * length];
            start = j;
            finish = start + length;
            length *= 2;
            if (pos)
               pos = j + (pos - i);
            while (i != finish)
               *j++ = *i++;
         }
         if (pos && pos != finish)
         { iterator i = finish;
            iterator j = i - 1;
            while (j != pos)
               *i- = *j-;
         }
         *finish++ = val;
         return pos;
      }
};
To enable the container, we add the following two lines to our gSOAP header file:

#include "simpleVector.h"
template  < class T > class simpleVector;

The container class should not be defined in the gSOAP header file. It must be defined in a separate header file (e.g. "simpleVector.h"). The template  < class T > class simpleVector declaration ensures that gSOAP will recognize simpleVector as a container class.
Caution: when parsing XML content the container elements may not be stored in the same order given in the XML content. When gSOAP parses XML it uses the insert container methods to store elements one by one. However, element content that is "forwarded" with href attributes will be appended to the container. Forwarding can take place with multi-referenced data that is referred to from the main part of the SOAP 1.1 XML message to the independent elements that carry ids. Therefore, your application should not rely on the preservation of the order of elements in a container.

10.11.9  Polymorphic Dynamic Arrays and Lists

Polymorphic arrays (arrays of polymorphic element types) can be encoded when declared as an array of pointers to class instances. and lists. For example:

class ns__Object
{
   public:
   ...
};
class ns__Data: public ns__Object
{
   public:
   ...
};
class ArrayOfObject
{
   public:
   ns__Object **__ptr; // pointer to array of pointers to Objects
   int __size; // number of Objects pointed to
   int __offset; // optional SOAP 1.1 array offset
};

The pointers in the array can point to the ns__Object base class or ns__Data derived class instances which will be serialized and deserialized accordingly in SOAP. That is, the array elements are polymorphic.

10.11.10  How to Change the Tag Names of the Elements of a SOAP Array or List

The __ptr field in a struct or class declaration of a dynamic array may have an optional suffix part that describes the name of the tags of the SOAP array XML elements. The suffix is part of the field name:

Type *__ptrarray_elt_name

The suffix describes the tag name to be used for all array elements. The usual identifier to XML translations apply, see Section 9.3. The default XML element tag name for array elements is item (which corresponds to the use of field name __ptritem).
Consider for example:

struct ArrayOfstring
{
   xsd__string *__ptrstring;    int __size; };

The array is serialized as:

<array xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:string[2]»
<string xsi:type="xsd:string»Hello</string>
<string xsi:type="xsd:string»World</string>
</array>

SOAP 1.1 and 1.2 do not require the use of a specific tag name for array elements. gSOAP will deserialize a SOAP array while ignoring the tag names. Certain XML Schemas used in doc/literal encoding may require the declaration of array element tag names.

10.12  Base64Binary XML Schema Type Encoding

The base64Binary XML Schema type is a special form of dynamic array declared with a pointer (__ptr) to an unsigned char array.
For example using a struct:

struct xsd__base64Binary
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.
The SOAP_ENC:base64 encoding is another type for base 64 binary encoding specified by the SOAP data type schema and some SOAP applications may use this form (as indicated by their WSDL descriptions). It is declared by:

struct SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate SOAP-ENC:base64 serializers and deserializers.
The advantage of using a class is that methods can be used to initialize and manipulate the __ptr and __size fields. The user can add methods to this class to do this. For example:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
   xsd__base64Binary(); // Constructor
   xsd__base64Binary(struct soap *soap, int n); // Constructor
   ~xsd__base64Binary(); // Destructor
   unsigned char *location(); // returns the memory location
   int size(); // returns the number of bytes
};

Here are example method implementations:

xsd__base64Binary::xsd__base64Binary()
{
   __ptr = NULL;
   __size = 0;
}
xsd__base64Binary::xsd__base64Binary(struct soap *soap, int n)
{
   __ptr = (unsigned char*)soap_malloc(soap, n);
   __size = n;
}
xsd__base64Binary::~xsd__base64Binary()
{ }
unsigned char *xsd__base64Binary::location()
{
   return __ptr;
}
int xsd__base64Binary::size()
{
   return __size;
}

The following example in C/C++ reads from a raw image file and encodes the image in SOAP using the base64Binary type:

...
FILE *fd = fopen("image.jpg", "rb");
xsd__base64Binary image(&soap, filesize(fd));
fread(image.location(), image.size(), 1, fd);
fclose(fd);
soap_begin(&soap);
image.soap_serialize(&soap);
image.soap_put(&soap, "jpegimage", NULL);
soap_end(&soap);
...

where filesize is a function that returns the size of a file given a file descriptor.
Reading the xsd:base64Binary encoded image.

...
xsd__base64Binary image;
soap_begin(&soap);
image.get(&soap, "jpegimage");
soap_end(&soap);
...

The struct or class name soap_enc__base64 should be used for SOAP-ENC:base64 schema type instead of xsd__base64Binary.

10.13  hexBinary XML Schema Type Encoding

The hexBinary XML Schema type is a special form of dynamic array declared with the name xsd__hexBinary and a pointer (__ptr) to an unsigned char array.
For example, using a struct:

struct xsd__hexBinary
{
   unsigned char *__ptr;
   int __size;
};

Or using a class:

class xsd__hexBinary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.

10.14  Literal XML Encoding Style

gSOAP supports document/literal encoding by default. Just as with SOAP RPC encoding, literal encoding requires the XML Schema of the message data to be provided e.g. in WSDL in order for the gSOAP compiler to generate the (de)serialization routines. Alternatively, the optional DOM parser (dom.c and dom++.cpp) can be used to handle generic XML or arbitrary XML documents can be (de)serialized into regular C strings or wide character strings (wchar_t*) by gSOAP (see Section 10.14.1).
The //gsoap service encoding, //gsoap service method-encoding, and //gsoap service method-response-encoding directives explicitly enable SOAP encoded or literal encoded messages. For example, to enable RPC encoding style for the entire service, use:

//gsoap ns service encoding: encoded

To enable encoding for particular service methods, use:

//gsoap ns service method-encoding: myMethod encoded
int ns__myMethod(...)

To enable encoding for particular service methods responses when the method request is literal, use:

//gsoap ns service method-response-encoding: myMethod encoded
int ns__myMethod(...)

Instead of the encoded value, you can use literal, or a specific encoding style value.
Consider the following example that uses the directive to make the literal encoding explicit
   typedef pointer iterator;
   typedef const_pointer const_iterator;
protected:
   iterator start;
   iterator finish;
   size_t length;
public:
   simpleVector() { clear(); }
   ~simpleVector() { delete[] start; }
   void\ clear() { start = finish = NULL; }
   iterator begin() { return start; }
   const_iterator begin() const\ { return start; }
   iterator end() { return finish; }
   const_iterator end() const\ { return finish; }
   size_t size() const\ { return finish-start; }
   iterator insert(iterator pos, const_reference val)
      {
         if (!start)
            start = finish = new value_type[length = 4];
         else if (finish > = start + length)
         {
            iterator i = start;
            iterator j = new value_type[2 * length];
            start = j;
            finish = start + length;
            length *= 2;
            if (pos)
               pos = j + (pos - i);
            while (i != finish)
               *j++ = *i++;
         }
         if (pos && pos != finish)
         { iterator i = finish;
            iterator j = i - 1;
            while (j != pos)
               *i- = *j-;
         }
         *finish++ = val;
         return pos;
      }
};
To enable the container, we add the following two lines to our gSOAP header file:

#include "simpleVector.h"
template  < class T > class simpleVector;

The container class should not be defined in the gSOAP header file. It must be defined in a separate header file (e.g. "simpleVector.h"). The template  < class T > class simpleVector declaration ensures that gSOAP will recognize simpleVector as a container class.
Caution: when parsing XML content the container elements may not be stored in the same order given in the XML content. When gSOAP parses XML it uses the insert container methods to store elements one by one. However, element content that is "forwarded" with href attributes will be appended to the container. Forwarding can take place with multi-referenced data that is referred to from the main part of the SOAP 1.1 XML message to the independent elements that carry ids. Therefore, your application should not rely on the preservation of the order of elements in a container.

10.11.9  Polymorphic Dynamic Arrays and Lists

Polymorphic arrays (arrays of polymorphic element types) can be encoded when declared as an array of pointers to class instances. and lists. For example:

class ns__Object
{
   public:
   ...
};
class ns__Data: public ns__Object
{
   public:
   ...
};
class ArrayOfObject
{
   public:
   ns__Object **__ptr; // pointer to array of pointers to Objects
   int __size; // number of Objects pointed to
   int __offset; // optional SOAP 1.1 array offset
};

The pointers in the array can point to the ns__Object base class or ns__Data derived class instances which will be serialized and deserialized accordingly in SOAP. That is, the array elements are polymorphic.

10.11.10  How to Change the Tag Names of the Elements of a SOAP Array or List

The __ptr field in a struct or class declaration of a dynamic array may have an optional suffix part that describes the name of the tags of the SOAP array XML elements. The suffix is part of the field name:

Type *__ptrarray_elt_name

The suffix describes the tag name to be used for all array elements. The usual identifier to XML translations apply, see Section 9.3. The default XML element tag name for array elements is item (which corresponds to the use of field name __ptritem).
Consider for example:

struct ArrayOfstring
{
   xsd__string *__ptrstring;    int __size; };

The array is serialized as:

<array xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:string[2]»
<string xsi:type="xsd:string»Hello</string>
<string xsi:type="xsd:string»World</string>
</array>

SOAP 1.1 and 1.2 do not require the use of a specific tag name for array elements. gSOAP will deserialize a SOAP array while ignoring the tag names. Certain XML Schemas used in doc/literal encoding may require the declaration of array element tag names.

10.12  Base64Binary XML Schema Type Encoding

The base64Binary XML Schema type is a special form of dynamic array declared with a pointer (__ptr) to an unsigned char array.
For example using a struct:

struct xsd__base64Binary
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.
The SOAP_ENC:base64 encoding is another type for base 64 binary encoding specified by the SOAP data type schema and some SOAP applications may use this form (as indicated by their WSDL descriptions). It is declared by:

struct SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate SOAP-ENC:base64 serializers and deserializers.
The advantage of using a class is that methods can be used to initialize and manipulate the __ptr and __size fields. The user can add methods to this class to do this. For example:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
   xsd__base64Binary(); // Constructor
   xsd__base64Binary(struct soap *soap, int n); // Constructor
   ~xsd__base64Binary(); // Destructor
   unsigned char *location(); // returns the memory location
   int size(); // returns the number of bytes
};

Here are example method implementations:

xsd__base64Binary::xsd__base64Binary()
{
   __ptr = NULL;
   __size = 0;
}
xsd__base64Binary::xsd__base64Binary(struct soap *soap, int n)
{
   __ptr = (unsigned char*)soap_malloc(soap, n);
   __size = n;
}
xsd__base64Binary::~xsd__base64Binary()
{ }
unsigned char *xsd__base64Binary::location()
{
   return __ptr;
}
int xsd__base64Binary::size()
{
   return __size;
}

The following example in C/C++ reads from a raw image file and encodes the image in SOAP using the base64Binary type:

...
FILE *fd = fopen("image.jpg", "rb");
xsd__base64Binary image(&soap, filesize(fd));
fread(image.location(), image.size(), 1, fd);
fclose(fd);
soap_begin(&soap);
image.soap_serialize(&soap);
image.soap_put(&soap, "jpegimage", NULL);
soap_end(&soap);
...

where filesize is a function that returns the size of a file given a file descriptor.
Reading the xsd:base64Binary encoded image.

...
xsd__base64Binary image;
soap_begin(&soap);
image.get(&soap, "jpegimage");
soap_end(&soap);
...

The struct or class name soap_enc__base64 should be used for SOAP-ENC:base64 schema type instead of xsd__base64Binary.

10.13  hexBinary XML Schema Type Encoding

The hexBinary XML Schema type is a special form of dynamic array declared with the name xsd__hexBinary and a pointer (__ptr) to an unsigned char array.
For example, using a struct:

struct xsd__hexBinary
{
   unsigned char *__ptr;
   int __size;
};

Or using a class:

class xsd__hexBinary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.

10.14  Literal XML Encoding Style

gSOAP supports document/literal encoding by default. Just as with SOAP RPC encoding, literal encoding requires the XML Schema of the message data to be provided e.g. in WSDL in order for the gSOAP compiler to generate the (de)serialization routines. Alternatively, the optional DOM parser (dom.c and dom++.cpp) can be used to handle generic XML or arbitrary XML documents can be (de)serialized into regular C strings or wide character strings (wchar_t*) by gSOAP (see Section 10.14.1).
The //gsoap service encoding, //gsoap service method-encoding, and //gsoap service method-response-encoding directives explicitly enable SOAP encoded or literal encoded messages. For example, to enable RPC encoding style for the entire service, use:

//gsoap ns service encoding: encoded

To enable encoding for particular service methods, use:

//gsoap ns service method-encoding: myMethod encoded
int ns__myMethod(...)

To enable encoding for particular service methods responses when the method request is literal, use:

//gsoap ns service method-response-encoding: myMethod encoded
int ns__myMethod(...)

Instead of the encoded value, you can use literal, or a specific encoding style value.
Consider the following example that uses the directive to make the literal encoding explicit
   typedef pointer iterator;
   typedef const_pointer const_iterator;
protected:
   iterator start;
   iterator finish;
   size_t length;
public:
   simpleVector() { clear(); }
   ~simpleVector() { delete[] start; }
   void\ clear() { start = finish = NULL; }
   iterator begin() { return start; }
   const_iterator begin() const\ { return start; }
   iterator end() { return finish; }
   const_iterator end() const\ { return finish; }
   size_t size() const\ { return finish-start; }
   iterator insert(iterator pos, const_reference val)
      {
         if (!start)
            start = finish = new value_type[length = 4];
         else if (finish > = start + length)
         {
            iterator i = start;
            iterator j = new value_type[2 * length];
            start = j;
            finish = start + length;
            length *= 2;
            if (pos)
               pos = j + (pos - i);
            while (i != finish)
               *j++ = *i++;
         }
         if (pos && pos != finish)
         { iterator i = finish;
            iterator j = i - 1;
            while (j != pos)
               *i- = *j-;
         }
         *finish++ = val;
         return pos;
      }
};
To enable the container, we add the following two lines to our gSOAP header file:

#include "simpleVector.h"
template  < class T > class simpleVector;

The container class should not be defined in the gSOAP header file. It must be defined in a separate header file (e.g. "simpleVector.h"). The template  < class T > class simpleVector declaration ensures that gSOAP will recognize simpleVector as a container class.
Caution: when parsing XML content the container elements may not be stored in the same order given in the XML content. When gSOAP parses XML it uses the insert container methods to store elements one by one. However, element content that is "forwarded" with href attributes will be appended to the container. Forwarding can take place with multi-referenced data that is referred to from the main part of the SOAP 1.1 XML message to the independent elements that carry ids. Therefore, your application should not rely on the preservation of the order of elements in a container.

10.11.9  Polymorphic Dynamic Arrays and Lists

Polymorphic arrays (arrays of polymorphic element types) can be encoded when declared as an array of pointers to class instances. and lists. For example:

class ns__Object
{
   public:
   ...
};
class ns__Data: public ns__Object
{
   public:
   ...
};
class ArrayOfObject
{
   public:
   ns__Object **__ptr; // pointer to array of pointers to Objects
   int __size; // number of Objects pointed to
   int __offset; // optional SOAP 1.1 array offset
};

The pointers in the array can point to the ns__Object base class or ns__Data derived class instances which will be serialized and deserialized accordingly in SOAP. That is, the array elements are polymorphic.

10.11.10  How to Change the Tag Names of the Elements of a SOAP Array or List

The __ptr field in a struct or class declaration of a dynamic array may have an optional suffix part that describes the name of the tags of the SOAP array XML elements. The suffix is part of the field name:

Type *__ptrarray_elt_name

The suffix describes the tag name to be used for all array elements. The usual identifier to XML translations apply, see Section 9.3. The default XML element tag name for array elements is item (which corresponds to the use of field name __ptritem).
Consider for example:

struct ArrayOfstring
{
   xsd__string *__ptrstring;    int __size; };

The array is serialized as:

<array xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:string[2]»
<string xsi:type="xsd:string»Hello</string>
<string xsi:type="xsd:string»World</string>
</array>

SOAP 1.1 and 1.2 do not require the use of a specific tag name for array elements. gSOAP will deserialize a SOAP array while ignoring the tag names. Certain XML Schemas used in doc/literal encoding may require the declaration of array element tag names.

10.12  Base64Binary XML Schema Type Encoding

The base64Binary XML Schema type is a special form of dynamic array declared with a pointer (__ptr) to an unsigned char array.
For example using a struct:

struct xsd__base64Binary
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.
The SOAP_ENC:base64 encoding is another type for base 64 binary encoding specified by the SOAP data type schema and some SOAP applications may use this form (as indicated by their WSDL descriptions). It is declared by:

struct SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate SOAP-ENC:base64 serializers and deserializers.
The advantage of using a class is that methods can be used to initialize and manipulate the __ptr and __size fields. The user can add methods to this class to do this. For example:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
   xsd__base64Binary(); // Constructor
   xsd__base64Binary(struct soap *soap, int n); // Constructor
   ~xsd__base64Binary(); // Destructor
   unsigned char *location(); // returns the memory location
   int size(); // returns the number of bytes
};

Here are example method implementations:

xsd__base64Binary::xsd__base64Binary()
{
   __ptr = NULL;
   __size = 0;
}
xsd__base64Binary::xsd__base64Binary(struct soap *soap, int n)
{
   __ptr = (unsigned char*)soap_malloc(soap, n);
   __size = n;
}
xsd__base64Binary::~xsd__base64Binary()
{ }
unsigned char *xsd__base64Binary::location()
{
   return __ptr;
}
int xsd__base64Binary::size()
{
   return __size;
}

The following example in C/C++ reads from a raw image file and encodes the image in SOAP using the base64Binary type:

...
FILE *fd = fopen("image.jpg", "rb");
xsd__base64Binary image(&soap, filesize(fd));
fread(image.location(), image.size(), 1, fd);
fclose(fd);
soap_begin(&soap);
image.soap_serialize(&soap);
image.soap_put(&soap, "jpegimage", NULL);
soap_end(&soap);
...

where filesize is a function that returns the size of a file given a file descriptor.
Reading the xsd:base64Binary encoded image.

...
xsd__base64Binary image;
soap_begin(&soap);
image.get(&soap, "jpegimage");
soap_end(&soap);
...

The struct or class name soap_enc__base64 should be used for SOAP-ENC:base64 schema type instead of xsd__base64Binary.

10.13  hexBinary XML Schema Type Encoding

The hexBinary XML Schema type is a special form of dynamic array declared with the name xsd__hexBinary and a pointer (__ptr) to an unsigned char array.
For example, using a struct:

struct xsd__hexBinary
{
   unsigned char *__ptr;
   int __size;
};

Or using a class:

class xsd__hexBinary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.

10.14  Literal XML Encoding Style

gSOAP supports document/literal encoding by default. Just as with SOAP RPC encoding, literal encoding requires the XML Schema of the message data to be provided e.g. in WSDL in order for the gSOAP compiler to generate the (de)serialization routines. Alternatively, the optional DOM parser (dom.c and dom++.cpp) can be used to handle generic XML or arbitrary XML documents can be (de)serialized into regular C strings or wide character strings (wchar_t*) by gSOAP (see Section 10.14.1).
The //gsoap service encoding, //gsoap service method-encoding, and //gsoap service method-response-encoding directives explicitly enable SOAP encoded or literal encoded messages. For example, to enable RPC encoding style for the entire service, use:

//gsoap ns service encoding: encoded

To enable encoding for particular service methods, use:

//gsoap ns service method-encoding: myMethod encoded
int ns__myMethod(...)

To enable encoding for particular service methods responses when the method request is literal, use:

//gsoap ns service method-response-encoding: myMethod encoded
int ns__myMethod(...)

Instead of the encoded value, you can use literal, or a specific encoding style value.
Consider the following example that uses the directive to make the literal encoding explicit
   typedef pointer iterator;
   typedef const_pointer const_iterator;
protected:
   iterator start;
   iterator finish;
   size_t length;
public:
   simpleVector() { clear(); }
   ~simpleVector() { delete[] start; }
   void\ clear() { start = finish = NULL; }
   iterator begin() { return start; }
   const_iterator begin() const\ { return start; }
   iterator end() { return finish; }
   const_iterator end() const\ { return finish; }
   size_t size() const\ { return finish-start; }
   iterator insert(iterator pos, const_reference val)
      {
         if (!start)
            start = finish = new value_type[length = 4];
         else if (finish > = start + length)
         {
            iterator i = start;
            iterator j = new value_type[2 * length];
            start = j;
            finish = start + length;
            length *= 2;
            if (pos)
               pos = j + (pos - i);
            while (i != finish)
               *j++ = *i++;
         }
         if (pos && pos != finish)
         { iterator i = finish;
            iterator j = i - 1;
            while (j != pos)
               *i- = *j-;
         }
         *finish++ = val;
         return pos;
      }
};
To enable the container, we add the following two lines to our gSOAP header file:

#include "simpleVector.h"
template  < class T > class simpleVector;

The container class should not be defined in the gSOAP header file. It must be defined in a separate header file (e.g. "simpleVector.h"). The template  < class T > class simpleVector declaration ensures that gSOAP will recognize simpleVector as a container class.
Caution: when parsing XML content the container elements may not be stored in the same order given in the XML content. When gSOAP parses XML it uses the insert container methods to store elements one by one. However, element content that is "forwarded" with href attributes will be appended to the container. Forwarding can take place with multi-referenced data that is referred to from the main part of the SOAP 1.1 XML message to the independent elements that carry ids. Therefore, your application should not rely on the preservation of the order of elements in a container.

10.11.9  Polymorphic Dynamic Arrays and Lists

Polymorphic arrays (arrays of polymorphic element types) can be encoded when declared as an array of pointers to class instances. and lists. For example:

class ns__Object
{
   public:
   ...
};
class ns__Data: public ns__Object
{
   public:
   ...
};
class ArrayOfObject
{
   public:
   ns__Object **__ptr; // pointer to array of pointers to Objects
   int __size; // number of Objects pointed to
   int __offset; // optional SOAP 1.1 array offset
};

The pointers in the array can point to the ns__Object base class or ns__Data derived class instances which will be serialized and deserialized accordingly in SOAP. That is, the array elements are polymorphic.

10.11.10  How to Change the Tag Names of the Elements of a SOAP Array or List

The __ptr field in a struct or class declaration of a dynamic array may have an optional suffix part that describes the name of the tags of the SOAP array XML elements. The suffix is part of the field name:

Type *__ptrarray_elt_name

The suffix describes the tag name to be used for all array elements. The usual identifier to XML translations apply, see Section 9.3. The default XML element tag name for array elements is item (which corresponds to the use of field name __ptritem).
Consider for example:

struct ArrayOfstring
{
   xsd__string *__ptrstring;    int __size; };

The array is serialized as:

<array xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:string[2]»
<string xsi:type="xsd:string»Hello</string>
<string xsi:type="xsd:string»World</string>
</array>

SOAP 1.1 and 1.2 do not require the use of a specific tag name for array elements. gSOAP will deserialize a SOAP array while ignoring the tag names. Certain XML Schemas used in doc/literal encoding may require the declaration of array element tag names.

10.12  Base64Binary XML Schema Type Encoding

The base64Binary XML Schema type is a special form of dynamic array declared with a pointer (__ptr) to an unsigned char array.
For example using a struct:

struct xsd__base64Binary
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.
The SOAP_ENC:base64 encoding is another type for base 64 binary encoding specified by the SOAP data type schema and some SOAP applications may use this form (as indicated by their WSDL descriptions). It is declared by:

struct SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate SOAP-ENC:base64 serializers and deserializers.
The advantage of using a class is that methods can be used to initialize and manipulate the __ptr and __size fields. The user can add methods to this class to do this. For example:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
   xsd__base64Binary(); // Constructor
   xsd__base64Binary(struct soap *soap, int n); // Constructor
   ~xsd__base64Binary(); // Destructor
   unsigned char *location(); // returns the memory location
   int size(); // returns the number of bytes
};

Here are example method implementations:

xsd__base64Binary::xsd__base64Binary()
{
   __ptr = NULL;
   __size = 0;
}
xsd__base64Binary::xsd__base64Binary(struct soap *soap, int n)
{
   __ptr = (unsigned char*)soap_malloc(soap, n);
   __size = n;
}
xsd__base64Binary::~xsd__base64Binary()
{ }
unsigned char *xsd__base64Binary::location()
{
   return __ptr;
}
int xsd__base64Binary::size()
{
   return __size;
}

The following example in C/C++ reads from a raw image file and encodes the image in SOAP using the base64Binary type:

...
FILE *fd = fopen("image.jpg", "rb");
xsd__base64Binary image(&soap, filesize(fd));
fread(image.location(), image.size(), 1, fd);
fclose(fd);
soap_begin(&soap);
image.soap_serialize(&soap);
image.soap_put(&soap, "jpegimage", NULL);
soap_end(&soap);
...

where filesize is a function that returns the size of a file given a file descriptor.
Reading the xsd:base64Binary encoded image.

...
xsd__base64Binary image;
soap_begin(&soap);
image.get(&soap, "jpegimage");
soap_end(&soap);
...

The struct or class name soap_enc__base64 should be used for SOAP-ENC:base64 schema type instead of xsd__base64Binary.

10.13  hexBinary XML Schema Type Encoding

The hexBinary XML Schema type is a special form of dynamic array declared with the name xsd__hexBinary and a pointer (__ptr) to an unsigned char array.
For example, using a struct:

struct xsd__hexBinary
{
   unsigned char *__ptr;
   int __size;
};

Or using a class:

class xsd__hexBinary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.

10.14  Literal XML Encoding Style

gSOAP supports document/literal encoding by default. Just as with SOAP RPC encoding, literal encoding requires the XML Schema of the message data to be provided e.g. in WSDL in order for the gSOAP compiler to generate the (de)serialization routines. Alternatively, the optional DOM parser (dom.c and dom++.cpp) can be used to handle generic XML or arbitrary XML documents can be (de)serialized into regular C strings or wide character strings (wchar_t*) by gSOAP (see Section 10.14.1).
The //gsoap service encoding, //gsoap service method-encoding, and //gsoap service method-response-encoding directives explicitly enable SOAP encoded or literal encoded messages. For example, to enable RPC encoding style for the entire service, use:

//gsoap ns service encoding: encoded

To enable encoding for particular service methods, use:

//gsoap ns service method-encoding: myMethod encoded
int ns__myMethod(...)

To enable encoding for particular service methods responses when the method request is literal, use:

//gsoap ns service method-response-encoding: myMethod encoded
int ns__myMethod(...)

Instead of the encoded value, you can use literal, or a specific encoding style value.
Consider the following example that uses the directive to make the literal encoding explicit
   typedef pointer iterator;
   typedef const_pointer const_iterator;
protected:
   iterator start;
   iterator finish;
   size_t length;
public:
   simpleVector() { clear(); }
   ~simpleVector() { delete[] start; }
   void\ clear() { start = finish = NULL; }
   iterator begin() { return start; }
   const_iterator begin() const\ { return start; }
   iterator end() { return finish; }
   const_iterator end() const\ { return finish; }
   size_t size() const\ { return finish-start; }
   iterator insert(iterator pos, const_reference val)
      {
         if (!start)
            start = finish = new value_type[length = 4];
         else if (finish > = start + length)
         {
            iterator i = start;
            iterator j = new value_type[2 * length];
            start = j;
            finish = start + length;
            length *= 2;
            if (pos)
               pos = j + (pos - i);
            while (i != finish)
               *j++ = *i++;
         }
         if (pos && pos != finish)
         { iterator i = finish;
            iterator j = i - 1;
            while (j != pos)
               *i- = *j-;
         }
         *finish++ = val;
         return pos;
      }
};
To enable the container, we add the following two lines to our gSOAP header file:

#include "simpleVector.h"
template  < class T > class simpleVector;

The container class should not be defined in the gSOAP header file. It must be defined in a separate header file (e.g. "simpleVector.h"). The template  < class T > class simpleVector declaration ensures that gSOAP will recognize simpleVector as a container class.
Caution: when parsing XML content the container elements may not be stored in the same order given in the XML content. When gSOAP parses XML it uses the insert container methods to store elements one by one. However, element content that is "forwarded" with href attributes will be appended to the container. Forwarding can take place with multi-referenced data that is referred to from the main part of the SOAP 1.1 XML message to the independent elements that carry ids. Therefore, your application should not rely on the preservation of the order of elements in a container.

10.11.9  Polymorphic Dynamic Arrays and Lists

Polymorphic arrays (arrays of polymorphic element types) can be encoded when declared as an array of pointers to class instances. and lists. For example:

class ns__Object
{
   public:
   ...
};
class ns__Data: public ns__Object
{
   public:
   ...
};
class ArrayOfObject
{
   public:
   ns__Object **__ptr; // pointer to array of pointers to Objects
   int __size; // number of Objects pointed to
   int __offset; // optional SOAP 1.1 array offset
};

The pointers in the array can point to the ns__Object base class or ns__Data derived class instances which will be serialized and deserialized accordingly in SOAP. That is, the array elements are polymorphic.

10.11.10  How to Change the Tag Names of the Elements of a SOAP Array or List

The __ptr field in a struct or class declaration of a dynamic array may have an optional suffix part that describes the name of the tags of the SOAP array XML elements. The suffix is part of the field name:

Type *__ptrarray_elt_name

The suffix describes the tag name to be used for all array elements. The usual identifier to XML translations apply, see Section 9.3. The default XML element tag name for array elements is item (which corresponds to the use of field name __ptritem).
Consider for example:

struct ArrayOfstring
{
   xsd__string *__ptrstring;    int __size; };

The array is serialized as:

<array xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:string[2]»
<string xsi:type="xsd:string»Hello</string>
<string xsi:type="xsd:string»World</string>
</array>

SOAP 1.1 and 1.2 do not require the use of a specific tag name for array elements. gSOAP will deserialize a SOAP array while ignoring the tag names. Certain XML Schemas used in doc/literal encoding may require the declaration of array element tag names.

10.12  Base64Binary XML Schema Type Encoding

The base64Binary XML Schema type is a special form of dynamic array declared with a pointer (__ptr) to an unsigned char array.
For example using a struct:

struct xsd__base64Binary
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate base64Binary serializers and deserializers.
The SOAP_ENC:base64 encoding is another type for base 64 binary encoding specified by the SOAP data type schema and some SOAP applications may use this form (as indicated by their WSDL descriptions). It is declared by:

struct SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

Or with a class:

class SOAP_ENC__base64
{
   unsigned char *__ptr;
   int __size;
};

When compiled by the gSOAP stub and skeleton compiler, this header file specification will generate SOAP-ENC:base64 serializers and deserializers.
The advantage of using a class is that methods can be used to initialize and manipulate the __ptr and __size fields. The user can add methods to this class to do this. For example:

class xsd__base64Binary
{
   public:
   unsigned char *__ptr;
   int __size;
   xsd__base64Binary(); // Constructor
   xsd__base64Binary(struct soap *soap, int n); // Constructor
   ~xsd__base64Binary(); // Destructor
   unsigned char *location(); // returns the memory location
   int size(); // returns the number of bytes
};

Here are example method implementations:

xsd__base64Binary::xsd__base64Binary()
{
   __ptr = NULL;
   __size = 0;
}
xsd__base64Binary::xsd__base64Binary(struct soap *soap, int n)
{
   __ptr = (unsigned char*)soap_malloc(soap, n);
   __size = n;
}
xsd__base64Binary::~xsd__base64Binary()
{ }
unsigned char *xsd__base64Binary::location()
{
   return __ptr;
}
int xsd__base64Binary::size()
{
   return __size;
}

The following example in C/C++ reads from a raw image file and encodes the image in SOAP using the base64Binary type:

...
FILE *fd = fopen("image.jpg", "rb");
xsd__base64Binary image(&soap, filesize(fd));
fread(image.location(), image.size(), 1, fd);
fclose(fd);
soap_begin(&soap);
image.soap_serialize(&soap);
image.soap_put(&soap, "jpegimage", NULL);
soap_end(&soap);
...

where filesize is a function that returns the size of a file given a file descriptor.
Reading the xsd:base64Binary encoded image.

...
xsd__base64Binary image;
soap_begin(&soap);
image.get(&soap, "jpe