2 XML Data Bindings {#mainpage}
7 This is a detailed overview of the gSOAP XML data bindings concepts and
8 implementation. At the end of
this document two examples are given to
9 illustrate the application of data bindings.
11 The first example `address.cpp` shows how to use wsdl2h to bind an XML
12 schema to C++. The C++ application reads and writes an XML file into and from a
13 C++
"address book" data structure. The C++ data structure is an STL vector of
16 The second example `graph.cpp` shows how XML is serialized as a tree, digraph,
17 and cyclic graph. The digraph and cyclic graph serialization rules are similar
18 to SOAP 1.1/1.2 encoded multi-ref elements with
id-ref attributes to link
19 elements through IDREF XML
"pointers".
21 These examples demonstrate XML data bindings only
for relatively simple data
22 structures and types. The gSOAP tools support more than just these type of
23 structures, which we will explain in the next sections. Support
for XML schema
24 components is practically unlimited. The wsdl2h tool maps schemas to C and C++
25 using built-in intuitive mapping rules,
while allowing the mappings to be
26 customized
using a `typemap.dat` file with mapping instructions
for wsdl2h.
28 The information in
this document is applicable to gSOAP 2.8.24 and higher, which
29 supports C++11 features. However, C++11 is not required to use
this material
30 and follow the example, unless we need smart pointers and scoped enumerations.
31 While most of the examples in
this document are given in C++, the concepts also
32 apply to C with the exception of containers, smart pointers, classes and their
33 methods. None of these exceptions limit the use of the gSOAP tools
for C in any
36 The data binding concepts described in
this document have somewhat changed
37 and improved over the years since the first version of gSOAP was developed in
38 1999 (the project was called a
"XML/SOAP stub/skeleton compiler" back
39 then). However, the principle of mapping XSD components to C/C++ types and vice
40 versa was envisioned and implemented early on in research conducted by Dr. van
41 Engelen at the Florida State University and subsequently adopted by other
42 tools, including Java web services and in C# WCF.
45 Mapping WSDL and XML schemas to C/C++ {#tocpp}
46 =====================================
48 To convert WSDL and XML schemas (XSD files), we use the wsdl2h command to
49 generate the data binding
interface code in a special gSOAP header file:
51 wsdl2h [options] -o file.h ... XSD and WSDL files ...
53 This converts WSDL and XSD files to C++ (or pure C with wsdl2h option `-c`) and
54 saves a special `file.h` data binding interface file.
56 The WSDL 1.1/2.0, SOAP 1.1/1.2, and XSD 1.0/1.1 standards are supported by the
57 gSOAP tools. In addition, the most popular WS specifications are also
58 supported, including WS-Addressing, WS-ReliableMessaging, WS-Discovery,
59 WS-Security, WS-Policy, WS-SecurityPolicy, and WS-SecureConversation.
61 This document focusses on XML data bindings and mapping C/C++ to XML 1.0/1.1
62 and XSD 1.0/1.1. This covers all of the following standard XSD components with
63 their optional `[ attributes ]` properties:
65 any [minOccurs, maxOccurs]
68 choice [minOccurs, maxOccurs]
69 sequence [minOccurs, maxOccurs]
71 attributeGroup [name, ref]
72 attribute [name, ref, type, use, default, fixed, form, wsdl:arrayType]
73 element [name, ref, type, default, fixed, form, nillable, abstract, substitutionGroup, minOccurs, maxOccurs]
75 complexType [name, abstract, mixed]
77 And also the following standard XSD components:
79 import imports a schema into the importing schema for referencing
80 include include schema component definitions into a schema
81 override override by replacing schema component definitions
82 redefine extend or restrict schema component definitions
83 annotation annotates a component
85 The XSD facets and their mappings to C/C++ are:
87 enumeration maps to enum
88 simpleContent maps to class/struct wrapper with __item member
89 complexContent maps to class/struct
90 list maps to enum* bitmask (enum* enumerates up to 64 bit masks)
91 extension through inheritance
92 restriction partly through inheritance and redeclaration
93 length restricts content length
94 minLength restricst content length
95 maxLength restricst content length
96 minInclusive restricts numerical value range
97 maxInclusive restricts numerical value range
98 minExclusive restricts numerical value range
99 maxExclusive restricts numerical value range
100 precision maps to float/double but constraint is not validated
101 scale maps to float/double but constraint is not validated
102 totalDigits maps to float/double but constraint is not validated
103 fractionDigits maps to float/double but constraint is not validated
104 pattern must define `soap::fsvalidate` callback to validate patterns
105 union maps to string of values
107 All primitive XSD types are supported, including but not limited to the
110 anyType maps to
_XML string with literal XML content (or DOM with wsdl2h option -d)
111 anyURI maps to string
112 string maps to string (char*/wchar_t*/std::string/std::wstring)
113 boolean maps to bool (C++) or enum xsd__boolean (C)
114 byte maps to char (int8_t)
115 short maps to short (int16_t)
116 int maps to int (int32_t)
117 long maps to LONG64 (long long and int64_t)
118 unsignedByte maps to unsigned char (uint8_t)
119 unsignedShort maps to unsigned short (uint16_t)
120 unsignedInt maps to unsigned int (uint32_t)
121 unsignedLong maps to ULONG64 (unsigned long long and uint64_t)
123 double maps to double
124 integer maps to string
125 decimal maps to string, or use "#import "custom/long_double.h"
126 precisionDecimal maps to string
127 duration maps to string, or use "#import "custom/duration.h"
128 dateTime maps to time_t, or use "#import "custom/struct_tm.h"
129 time maps to string, or use "#import "custom/long_time.h"
130 date maps to string, or use "#import "custom/struct_tm_date.h"
131 hexBinary maps to class/struct xsd__hexBinary
132 base64Bianry maps to class/struct xsd__base64Binary
133 QName maps to
_QName (URI normalization rules are applied)
135 All other primitive XSD types not listed above are mapped to strings, by
136 generating a typedef. For example, xsd:token is bound to a C++ or C string,
137 which associates a value space to the type with the appropriate XSD type name
138 used by the soapcpp2-generated serializers:
140 typedef std::string xsd__token;
141 typedef char *xsd__token;
143 It is possible to remap types by adding the appropriate mapping rules to
144 `typemap.dat` as explained in the next section.
147 Using typemap.dat to customize generated bindings {#typemap}
148 =================================================
150 We use a `typemap.dat` file to redefine
namespace prefixes and to customize
151 type bindings for the the generated header files produced by the wsdl2h tool.
152 The `typemap.dat` is the default file processed by wsdl2h. Use wsdl2h option
153 `-t` to specify an alternate file.
155 Declarations in `typemap.dat` can be broken up over multiple lines by
156 continuing on the next line by ending each line to be continued with a
159 XML namespace bindings {#typemap1}
160 ----------------------
162 The wsdl2h tool generates C/C++ type declarations that use `ns1`, `ns2`, etc.
163 as URI schema-binding prefixes. These
default prefixes are generated somewhat
164 arbitrarily
for each schema URI, meaning that their ordering may change
165 depending on the WSDL and XSD order of processing with wsdl2h.
167 It is **strongly recommended** to declare your own prefix
for each schema URI
168 to enhance maintaince of your code. This is to anticipate possible changes of
169 the schema(s) and/or the binding URI(s) and/or the tooling procedures.
171 Therefore, the first and foremost important thing to do is to define prefix-URI
172 bindings for our C/C++ code by adding the following line(s) to our
173 `typemap.dat` or make a copy of this file and add the line(s) that bind our
174 choice of prefix name to each URI:
182 This produces `g__name` C/C++ type names that are bound to the "urn:graph"
183 schema by association of `
g` to the C/C++ types.
185 This means that `<
g:name xmlns:
g="urn:graph">` is parsed as an instance of a
186 `g__name` C/C++ type. Also `<x:name xmlns:x="urn:graph">` parses as an instance
187 of `g__name`, because the prefix `x` has the same URI value `urn:graph`.
188 Prefixes in XML have local scopes (like variables in a block).
190 The first run of wsdl2h will reveal the URIs, so we do not need to search WSDLs
191 and XSD files for all of the target namespaces.
193 XSD type bindings {#typemap2}
196 Custom C/C++ type bindings can be declared in `typemap.dat` to associate C/C++
197 types with specific schema types. These type bindings have four parts:
199 prefix__type = declaration | use | ptruse
203 - `prefix__type` is the schema type to be customized (the `prefix__type` name
204 uses the common
double underscore naming convention);
205 - `declaration` declares the C/C++ type in the wsdl2h-generated header file.
206 This part can be empty
if no
explicit declaration is needed;
207 - `use` is an optional part that specifies how the C/C++ type is used in the
208 code. When omitted, it is the same as `prefix__type`;
209 - `ptruse` is an optional part that specifies how the type is used as a
210 pointer type. By
default it is the `use` type name with a `*` or C++11
211 `std::shared_ptr<>` (see further below).
213 For example, to map xsd:duration to a `
long long` (`LONG64`) milliseconds
214 value, we can use the custom serializer declared in `custom/duration.h` by
215 adding the following line to `typemap.dat`:
217 xsd__duration =
#import "custom/duration.h" | xsd__duration
219 Here, we could have omitted the second field, because `xsd__duration` is the
220 name that wsdl2h uses to identify
this type.
222 To map xsd:
string to `
wchar_t*` wide strings:
224 xsd__string = |
wchar_t* |
wchar_t*
226 Note that the first field is empty, because `
wchar_t` is a C type and does not
227 need to be declared. A `ptruse` field is given so that we
do not end up
228 generating the wrong pointer types, such as `
wchar_t**` and
229 `std::shared_ptr<wchar_t>`.
231 When the
auto-generated declaration should be preserved but the `use` or
232 `ptruse` fields replaced, then we use an ellipsis
for the declaration part:
234 prefix__type = ... | use | ptruse
236 This is useful to map schema polymorphic types to C types
for example, where we
237 need to be able to both handle a base type and its extensions as per schema
238 extensibility. Say we have a base type called ns:base that is extended, then we
239 can remap
this to a C type that permits referening the extended types via a
242 ns__base = ... |
int __type_base;
void*
244 such that `__type_base` and `
void*` are used to (de)serialize any data type,
245 including base and its derived types.
247 Class/struct member additions {#typemap3}
248 -----------------------------
250 All generated classes and structs can be augmented with additional
251 members such as methods, constructors and destructors, and
private members:
253 prefix__type = $ member-declaration
255 For example, we can add method declarations and
private members to a
class, say
256 `ns__record` as follows:
258 ns__record = $ ns__record(
const ns__record &);
259 ns__record = $
void print();
260 ns__record = $
private:
int status;
262 Note that method declarations cannot include any code, because soapcpp2
's input
263 permits only type declarations, not code.
265 Replacing XSD types by equivalent alternatives {#typemap4}
266 ----------------------------------------------
268 Type replacements can be given to replace one type entirely with another given
271 prefix__type1 == prefix__type2
273 This replaces all `prefix__type1` by `prefix__type2` in the wsdl2h output.
274 However, care muse be taken not to agressively replace types, because this can
275 cause XML validation to fail when a value-type mismatch is encountered in the
276 XML input. Therefore, only replace similar types with other similar types that
277 are wider (e.g. `short` by `int` and `float` by `double`).
279 The built-in typemap.dat variables $CONTAINER and $POINTER {#typemap5}
280 ----------------------------------------------------------
282 The `typemap.dat` `$CONTAINER` variable defines the container to emit in the
283 generated declarations, which is `std::vector` by default. For example:
285 $CONTAINER = std::list
287 The `typemap.dat` `$POINTER` variable defines the smart pointer to emit in the
288 generated declarations, which replaces the use of `*` pointers. For example:
290 $POINTER = std::shared_ptr
292 Not all pointers in the generated output can be replaced by smart pointers when
293 standard pointers are used as union members and pointers to arrays.
295 User-defined content {#typemap6}
298 Any other content to be generated by wsdl2h can be included in `typemap.dat` by
299 enclosing it within brackets `[` and `]`. These brackets MUST appear at the
302 For example, we can add an `#import "wsa5.h"` directive to the wsdl2h-generated
309 which emits the `#import "wsa5.h"` literally at the start of the
310 wsdl2h-generated header file.
313 Mapping C/C++ to XML schema {#toxsd}
314 ===========================
316 The soapcpp2 command generates the data binding implementation code from a data
317 binding interface `file.h`:
319 soapcpp2 [options] file.h
321 where `file.h` is a gSOAP header file that declares the XML data binding
322 interface. The `file.h` is typically generated by wsdl2h, but we can also
323 declare one ourself. If so, we add gSOAP directives and declare in this file
324 all our C/C++ types we want to serialize in XML. We can also declare functions
325 that will be converted to service operations by soapcpp2.
327 Global function declarations define service operations, which are of the form:
329 int ns__name(arg1, arg2, ..., argn, result);
331 where `arg1`, `arg2`, ..., `argn` are formal argument declarations of the input
332 and `result` is a formal argument for the output, which must be a pointer or
333 reference to the result object to be populated. More information can be found
334 in the gSOAP user guide.
336 Overview of serializable C/C++ types {#toxsd1}
337 ------------------------------------
339 The following C/C++ types are supported by soapcpp2 and mapped to XSD types
340 and constructs. See the subsections below for more details or follow the links.
342 List of [C++ bool and C alternative](#toxsd3)
345 enum xsd__boolean C alternative bool
347 List of [enumerations and bitmasks](#toxsd4)
350 enum class C++11 scoped enumeration (soapcpp2 -c++11)
351 enum* a bitmask that enumerates values 1, 2, 4, 8, ...
352 enum* class C++11 scoped enumeration (soapcpp2 -c++11)
354 List of [numerical types](#toxsd5)
360 LONG64 64 bit integer
361 long long same as LONG64
362 unsigned char unsigned byte
363 unsigned short unsigned 16 bit integer
364 unsigned int unsigned 32 bit integer
365 unsigned long unsigned 32 bit integer
366 ULONG64 unsigned 64 bit integer
367 unsigned long long same as ULONG64
369 int16_t same as short
371 int64_t same as LONG64
372 uint8_t same as unsigned char
373 uint16_t same as unsigned short
374 uint32_t same as unsigned int
375 uint64_t same as ULONG64
376 size_t transient type (not serializable)
379 long double 128 bit float, use #import "custom/long_double.h"
380 typedef declares a type name, may restrict numeric range
382 List of [string types](#toxsd6)
386 std::string C++ string
387 std::wstring C++ wide string
388 char[N] fixed-size string, requires soapcpp2 option -b
389 _QName normalized QName content
390 _XML literal XML string content
391 typedef declares a type name, may restrict string length
393 List of [date and time types](#toxsd7)
395 time_t date and time point since epoch
396 struct tm date and time point, use #import "custom/struct_tm.h"
397 struct tm date point, use #import "custom/struct_tm_date.h"
398 struct timeval date and time point, use #import "custom/struct_timeval.h"
399 unsigned long long time point in microseconds, use #import "custom/long_time.h"
400 std::chrono::system_clock::time_point
401 date and time point, use #import "custom/chrono_time_point.h"
403 List of [time duration types](#toxsd8)
405 long long duration in milliseconds, use #import "custom/duration.h"
406 std::chrono::nanoseconds duration in nanoseconds, use #import "custom/chrono_duration.h"
408 List of [classes and structs](#toxsd9)
410 class C++ class with single inheritance only
411 struct C struct or C++ struct without inheritance
413 T[N] fixed-size array of type T
414 std::shared_ptr<T> C++11 smart shared pointer
415 std::unique_ptr<T> C++11 smart pointer
416 std::auto_ptr<T> C++ smart pointer
417 std::deque<T> use #import "stldeque.h"
418 std::list<T> use #import "stllist.h"
419 std::vector<T> use #import "stlvector.h"
420 std::set<T> use #import "stlset.h"
421 template<T> class a container with begin(), end(), size(), clear(), and insert() methods
422 union requires a discriminant member
423 void* requires a __type member to indicate the type of object pointed to
425 List of [special classes and structs](#toxsd10)
427 Array single and multidimensional SOAP Arrays
428 xsd__hexBinary binary content
429 xsd__base64Binary binary content and optional MIME/MTOM attachments
430 Wrapper complexTypes with simpleContent
432 Colon notation versus name prefixing {#toxsd2}
433 ------------------------------------
435 To bind C/C++ type names to XSD types, a simple form of name prefixing is used
436 by the gSOAP tools by prepending the XML namespace prefix to the C/C++ type
437 name with a pair of undescrores. This also ensures that name clashes cannot
438 occur when multiple WSDL and XSD files are converted to C/C++. Also, C++
439 namespaces are not sufficiently rich to capture XML schema namespaces
440 accurately, for example when class members are associated with schema elements
441 defined in another XML namespace and thus the XML namespace scope of the
442 member's name is relevant, not just its type.
444 However, from a C/C++ centric point of view
this can be cumbersome. Therefore,
445 colon notation is an alternative to physically augmenting C/C++ names with
448 For example, the following
class uses colon notation to bind the `record` class
449 to the `urn:types` schema:
462 The colon notation is stripped away by soapcpp2 when generating the data
463 binding implementation code
for our project. So the
final code just uses
464 `record` to identify
this class and its constructor/destructor.
466 When using colon notation we have to be consistent as we cannot use both forms
467 together. That is, `ns:record` differs from `ns__record` as a name.
469 C++ Bool and C alternative {#toxsd3}
470 --------------------------
472 The C++ `
bool` type is bound to built-in XSD type xsd:
boolean.
474 The C alternative is to define an enumeration:
476 enum xsd__boolean { false_, true_ };
478 or by defining an enumeration in C with pseudo-scoped enumeration values:
480 enum xsd__boolean { xsd__boolean__false, xsd__boolean__true };
482 The XML value space of these types is `
false` and `
true`, but also accepts `0`
485 To prevent name clashes, `false_` and `true_` have an underscore which are
486 removed in the XML value space.
488 Enumerations and bitmasks {#toxsd4}
489 -------------------------
491 Enumerations are mapped to XSD simpleType enumeration restrictions of
492 xsd:string, xsd:QName, and xsd:
long.
494 Consider
for example:
496 enum ns__Color { RED, WHITE, BLUE };
498 which maps to a simpleType restriction of xsd:
string in the soapcpp2-generated
501 <simpleType name=
"Color">
502 <restriction base=
"xsd:string">
503 <enumeration value=
"RED"/>
504 <enumeration value=
"WHITE"/>
505 <enumeration value=
"BLUE"/>
509 Enumeration name constants can be pseudo-scoped to prevent name clashes,
510 because enumeration name constants have a global scope in C and C++:
512 enum ns__Color { ns__Color__RED, ns__Color__WHITE, ns__Color__BLUE };
514 We can also use C++11 scoped enumerations to prevent name clashes:
516 enum class ns__Color : int { RED, WHITE, BLUE };
518 Here, the type part `:
int` is optional. In place of `
int` in the example
519 above, we can also use `int8_t`, `int16_t`, `int32_t`, or `int64_t`.
521 The XML value space of the enumertions defined above is `RED`, `WHITE`, and
524 Prefix-qualified enumeration name constants are mapped to simpleType
525 restrictions of xsd:QName,
for example:
527 enum ns__types { xsd__int, xsd__float };
529 which maps to a simpleType restriction of xsd:QName in the soapcpp2-generated
532 <simpleType name=
"types">
533 <restriction base=
"xsd:QName">
534 <enumeration value=
"xsd:int"/>
535 <enumeration value=
"xsd:float"/>
539 Enumeration name constants can be pseudo-numeric as follows:
541 enum ns__Primes { _3 = 3, _5 = 5, _7 = 7, _11 = 11 };
543 which maps to a simpleType restriction of `xsd:
long`:
545 <simpleType name=
"Color">
546 <restriction base=
"xsd:long">
547 <enumeration value=
"3"/>
548 <enumeration value=
"5"/>
549 <enumeration value=
"7"/>
550 <enumeration value=
"11"/>
554 The XML value space of
this type is `3`, `5`, `7`, and `11`.
556 Besides (pseudo-) scoped enumerations, another way to prevent name clashes
557 accross enumerations is to start an enumeration name constant with one
558 underscore or followed it by any number of underscores, which makes it
559 unique. The leading and trailing underscores are removed in the XML value
562 enum ns__ABC { A, B, C };
563 enum ns__BA { B, A };
564 enum ns__BA_ { B_, A_ };
566 The gSOAP soapcpp2 tool permits reusing enumeration name constants in other
567 (non-scoped) enumerations as
long as these values are assigned the same
568 constant. Therefore, the following is permitted:
570 enum ns__Primes { _3 = 3, _5 = 5, _7 = 7, _11 = 11 };
571 enum ns__Throws { _1 = 1, _2 = 2, _3 = 3, _4 = 4, _5 = 5, _6 = 6 };
573 A bitmask type is an `
enum*`
"product" enumeration with a geometric,
574 power-of-two sequence of values assigned to the name constants:
576 enum* ns__Options { SSL3, TLS10, TLS11, TLS12 };
578 where the product
enum assigns 1 to `SSL3`, 2 to `TLS10`, 4 to `TLS11`, and 8
579 to `TLS12`, which allows the enumeration values to be used in composing
580 bitmasks with `|` (bitwise or) `&` (bitwise and), and `~` (bitwise not):
582 enum ns__Options options = (
enum ns__Options)(SSL3 | TLS10 | TLS11 | TLS12);
589 The bitmask type maps to a simpleType list restriction of xsd:
string in the
590 soapcpp2-generated schema:
592 <simpleType name=
"Options">
594 <restriction base=
"xsd:string">
595 <enumeration value=
"SSL3"/>
596 <enumeration value=
"TLS10"/>
597 <enumeration value=
"TLS11"/>
598 <enumeration value=
"TLS12"/>
603 The XML value space of
this type consists of all 16 possible subsets of the
604 four values, represented by an XML
string with space-separated values. For
605 example, the bitmask `TLS10 | TLS11 | TLS12` equals 14 and is represented in by
606 the XML
string `TLS10 TLS11 TLS12`.
608 To convert `
enum` name constants to string, we use the soapcpp2
auto-generated
609 `
const char *soap_T2s(soap,
enum T)`
function.
611 To convert a
string to an `
enum` name constant, we use the soapcpp2
612 auto-generated `
int soap_s2T(soap,
const char *str,
enum T*)`
function.
614 Numerical types {#toxsd5}
617 Integer and floating point types are mapped to the equivalent built-in XSD
618 types with the same sign and bit width.
620 The `
size_t` type is
transient (not serializable) because its width is platform
621 dependent. We recommend to use `uint64_t` instead.
623 The XML value space of integer types are their decimal representations without
626 The XML value space of floating point types are their decimal representations.
627 The decimal representations are formatted with the printf format
string "%.9G"
628 for floats and the printf format
string "%.17lG" for double. The value space
629 includes the values `INF`, `-INF`, and `NAN`. To change the format
string, we
630 can change one of these `
struct soap` context data members:
632 const char * soap::float_format
633 const char * soap::double_format
635 Note that decimal conversions may result in a loss of precision of the least
638 A `
long double` 128 bit floating point value requires a custom serializer:
640 #
import "custom/long_double.h"
641 typedef long double xsd__decimal;
643 Compile and link your code with `custom/long_double.c`.
645 The range of a numerical type can be restricted with a
typedef:
647 typedef int ns__narrow -10:10;
649 which maps to a simpleType restriction of xsd:
int in the soapcpp2-generated
652 <simpleType name=
"narrow">
653 <restriction base=
"xsd:int">
654 <minInclusive value=
"-10"/>
655 <maxInclusive value=
"10"/>
659 The range of a
float type can only be restricted within integral bounds. This
660 restriction may be dropped in future releases.
662 String types {#toxsd6}
665 String types are mapped to the built-in xsd:
string and xsd:QName XSD types.
667 The wide strings `
wchar_t*` and `std::wstring` may contain Unicode that is
668 preserved in the XML value space.
670 Strings `
char*` and `std::string` can only contain extended Latin, but we can
671 store UTF-8 content that is preserved in the XML value space when the `
struct
672 soap` context is initialized with the flag `XML_C_UTFSTRING`.
674 Beware that many XML 1.0 parsers reject all control characters (those between
675 `#x1` and `#x1F`) except `#x9`, `#xA`, and `#xD`. With the newer XML 1.1
676 parsers (including gSOAP) you should be fine.
678 The length of a
string type can be restricted with a
typedef:
680 typedef std::string ns__password 6:16;
682 which maps to a simpleType restriction of xsd:
string in the soapcpp2-generated
685 <simpleType name=
"password">
686 <restriction base=
"xsd:string">
687 <minLength value=
"6"/>
688 <maxLength value=
"16"/>
692 In addition, an XSD regex pattern restriction can be associated with a
string
695 typedef std::string ns__password
"([a-zA-Z]|[0-9]|-)+" 6:16;
697 which maps to a simpleType restriction of xsd:
string in the soapcpp2-generated
700 <simpleType name=
"password">
701 <restriction base=
"xsd:string">
702 <pattern value=
"([a-zA-Z0-9]|-)+"/>
703 <minLength value=
"6"/>
704 <maxLength value=
"16"/>
708 Fixed-size strings (`
char[N]`) are rare occurrences in the wild, but apparently
709 still used in some projects to store strings. To facilitate fixed-size
string
710 serialization, use soapcpp2 option `-b`:
712 typedef char ns__buffer[10];
714 which maps to a simpleType restriction of xsd:
string in the soapcpp2-generated
717 <simpleType name=
"buffer">
718 <restriction base=
"xsd:string">
719 <maxLength value=
"9"/>
723 Note that fixed-size strings MUST contain NUL-terminated text and SHOULD NOT
724 contain raw binary data. Also, the length limitation is more restrictive
for
725 UTF-8 content (enabled with the `SOAP_C_UTFSTRING`) that requires multibyte
726 character encodings. As a consequence, UTF-8 content may be truncated to fit.
728 Note that raw binary data can be stored in a `xsd__base64Binary` or
729 `xsd__hexBinary` structure, or transmitted as a MIME attachment.
731 The built-in `
_QName` type is a regular C
string type (`
char*`) that maps to
732 xsd:QName but has the added advantage that it holds normalized qualified names.
733 There are actually two forms of normalized QName content, to ensure any QName
734 is represented accurately and uniquely:
739 where the first form is used when the prefix (and the binding URI) is defined
740 in the namespace table and is bound to a URI (see the .nsmap file). The second
741 form is used when the URI is not defined in the namespace table and therefore
742 no prefix is available to bind and normalize the URI to.
744 A `
_QName`
string may contain a sequence of space-separated QName values, not
745 just one, and all QName values are normalized to the format shown above.
747 To define a `std::
string` base type for xsd:QName, we use a typedef:
749 typedef std::
string xsd__QName;
751 The `xsd__QName`
string content is normalized, just as with the `
_QName`
754 To serialize strings that contain literal XML content to be reproduced in the
755 XML value space, use the built-in `
_XML`
string type, which is a regular C
756 string type (`
char*`) that maps to plain XML CDATA.
758 To define a `std::
string` base type for literal XML content, use a typedef:
760 typedef std::
string XML;
762 Strings can hold any of the values of the XSD built-in primitive types. We can
763 use a
string typedef to declare the use of the
string type as a XSD built-in
766 typedef std::
string xsd__token;
768 We MUST ensure that the
string values we populate in this type conform to the
769 XML standard, which in case of xsd:token is: the lexical and value spaces of
770 xsd:token are the sets of all strings after whitespace replacement of any
771 occurrence of `
#x9`, `#xA` , and `#xD` by `#x20` and collapsing.
773 Date and time types {#toxsd7}
776 The C/C++ `time_t` type is mapped to the built-in xsd:dateTime XSD type that
777 represents a date and time within a time zone (typically UTC).
779 The XML value space contains ISO 8601 Gregorian time instances of the form
780 `[-]CCYY-MM-DDThh:mm:ss.sss[Z|(+|-)hh:mm]`, where `Z` is the UTC time zone or a
781 time zone offset `(+|-)hh:mm]` from UTC is used.
783 A `time_t` value is considered and represented in UTC by the serializer.
785 Because the `time_t` value range is restricted to dates after 01/01/1970, care
786 must be taken to ensure the range of xsd:dateTime values in XML exchanges
do
787 not exceed the `time_t` range.
789 This restriction does not hold
for `
struct tm` (`<time.h>`), which we can use
790 to store and communicate a date and time in UTC without date range restrictions.
791 The serializer uses the `tm` data members directly for conversion to/from the
792 XML value space of xsd:dateTime:
808 The `
struct tm` type is mapped to the built-in xsd:dateTime XSD type and
809 serialized with the custom serializer `custom/struct_tm.h` that declares a
810 `xsd__dateTime` type:
812 #import "custom/struct_tm.h" // import typedef struct tm xsd__dateTime;
813 ... use xsd__dateTime ...
815 Compile and link your code with `custom/struct_tm.c`.
817 The `struct tm` type is mapped to the built-in xsd:date XSD type and serialized
818 with the custom serializer `custom/struct_tm_date.h` that declares a
821 #import "custom/struct_tm_date.h" // import typedef struct tm xsd__date;
822 ... use xsd__date ...
824 Compile and link your code with `custom/struct_tm_date.c`.
826 The XML value space of xsd:date are Gregorian calendar dates of the form
827 `[-]CCYY-MM-DD[Z|(+|-)hh:mm]`.
829 The `struct timeval` (`<sys/time.h>`) type is mapped to the built-in
830 xsd:dateTime XSD type and serialized with the custom serializer
831 `custom/struct_timeval.h` that declares a `xsd__dateTime` type:
833 #import "custom/struct_timeval.h" // import typedef struct timeval xsd__dateTime;
834 ... use xsd__dateTime ...
836 Compile and link your code with `custom/struct_timeval.c`.
838 Note that the same value range restrictions apply to `struct timeval` as they
839 apply to `time_t`. The added benefit of `struct timeval` is the addition of
840 a microsecond-precise clock:
848 An `
unsigned long long` (`ULONG64` or `uint64_t`) type that contains a 24 hour
849 time in microseconds UTC is mapped to the built-in xsd:time XSD type and
850 serialized with the custom serializer `custom/long_time.h` that declares a
853 #
import "custom/long_time.h"
854 ... use xsd__time ...
856 Compile and link your code with `custom/long_time.c`.
858 The XML value space of xsd:time are points in time recurring each day of the
859 form `hh:mm:ss.sss[Z|(+|-)hh:mm]`, where `Z` is the UTC time zone or a time
860 zone offset from UTC is used. The `xsd__time` value is always considered and
861 represented in UTC by the serializer.
863 A C++11 `std::chrono::system_clock::time_point` type is mapped to the built-in
864 xsd:dateTime XSD type and serialized with the custom serializer
865 `custom/chrono_time_point.h` that declares a `xsd__dateTime` type:
867 #import "custom/chrono_time_point.h"
868 ... use xsd__dateTime ...
870 Compile and link your code with `custom/chrono_time_point.cpp`.
872 Time duration types {#toxsd8}
875 The XML value space of xsd:duration are values of the form `PnYnMnDTnHnMnS`
876 where the capital letters are delimiters. Delimiters may be omitted when the
877 corresponding member is not used.
879 A `
long long` (`LONG64` or `int64_t`) type that contains a duration (time
880 lapse) in milliseconds is mapped to the built-in xsd:duration XSD type and
881 serialized with the custom serializer `custom/duration.h` that declares a
882 `xsd__duration` type:
884 #import "custom/duration.h"
885 ... use xsd__duration ...
887 Compile and link your code with `custom/duration.c`.
889 The duration type `xsd__duration` can represent 106,751,991,167 days forward
890 and backward with millisecond precision.
892 A C++11 `std::chrono::nanoseconds` type is mapped to the built-in xsd:duration
893 XSD type and serialized with the custom serializer `custom/chrono_duration.h`
894 that declares a `xsd__duration` type:
896 #import "custom/chrono_duration.h"
897 ... use xsd__duration ...
899 Compile and link your code with `custom/chrono_duration.cpp`.
901 Classes and structs {#toxsd9}
904 Classes and structs are mapped to XSD complexTypes. The XML value space
905 consists of XML elements with attributes and subelements, possibly constrained
906 by validation rules that enforce element and attribute occurrence contraints,
907 numerical value range constraints, and
string length and pattern constraints.
909 Classes that are declared with the gSOAP tools are limited to single
910 inheritence only. Structs cannot be inherited.
912 The
class and struct name is bound to an XML namespace by means of the prefix
913 naming convention or by using [colon notation](#toxsd1):
928 In the example above, we also added a context pointer to the `
struct soap` that
929 manages this instance. It is set when the instance is created in the engine's
930 context, for example when deserialized and populated by the engine.
932 The class maps to a complexType in the soapcpp2-generated schema:
934 <complexType name="record">
936 <element name="name" type="xsd:string" minOccurs="1" maxOccurs="1"/>
937 <element name="SSN" type="xsd:unsignedLong" minOccurs="1" maxOccurs="1"/>
938 <element name="spouse" type="ns:record" minOccurs="0" maxOccurs="1" nillable="true"/>
942 ### Serializable versus transient types and members
944 Public data members of a class or struct are serialized. Private and
protected
945 members are transient and not serializable.
947 Also `const` and `static` members are not serializable, with the exception of
948 `const char*` and `const wchar_t*`.
950 Types and specific class/struct members can be made transient by using the
953 extern class std::ostream;
959 static const int MAX = 1024;
962 By declaring `std::ostream`
transient we can use
this type where we need it and
963 without soapcpp2 complaining that
this class is not defined.
965 ### Volatile classes and structs
967 Classes and structs can be declared `volatile` with the gSOAP tools. This means
968 that they are already declared elsewhere in our project's source code. We do
969 not want soapcpp2 to generate a second definition for these types.
971 For example, `struct tm` is declared in `<time.h>`. We want it serializable and
972 serialize only a selection of its data members:
984 We can declare classes and structs `
volatile`
for any such types we want to
985 serialize by only providing the
public data members we want to serialize.
987 Colon notation comes in handy to bind an existing
class or struct to a schema.
988 For example, we can change the `tm` name as follows without affecting the code
989 that uses `struct tm` generated by soapcpp2:
991 volatile struct ns:tm { ... }
993 This
struct maps to a complexType in the soapcpp2-generated schema:
995 <complexType name="tm">
997 <element name="tm-sec" type="xsd:int" minOccurs="1" maxOccurs="1"/>
998 <element name="tm-min" type="xsd:int" minOccurs="1" maxOccurs="1"/>
999 <element name="tm-hour" type="xsd:int" minOccurs="1" maxOccurs="1"/>
1000 <element name="tm-mday" type="xsd:int" minOccurs="1" maxOccurs="1"/>
1001 <element name="tm-mon" type="xsd:int" minOccurs="1" maxOccurs="1"/>
1002 <element name="tm-year" type="xsd:int" minOccurs="1" maxOccurs="1"/>
1006 ### Mutable classes and structs
1008 Classes and structs can be declared `mutable` with the gSOAP tools. This means
1009 that their definition can be spread out over the source code. This promotes the
1010 concept of a class or struct as a *row of named values*, also known as a *named
1011 tuple*, that can be extended as needed with additional entries. Because these
1012 types differ from the traditional object-oriented principles of classes and
1013 objects, constructors and destructors cannot be defined (also because we cannot
1014 guarantee merging these into one such that all members will be initialized). A
1015 default constructor, copy constructor, assignment operation, and destructor
1018 mutable struct ns__tuple
1023 mutable struct ns__tuple
1029 The members are collected into one definition generated by soapcpp2. Members
1030 may be repeated from one definition to another, but only
if their associated
1031 types are identical. So a third extension with a `value` member with a
1032 different type fails:
1034 mutable struct ns__tuple
1039 The `
mutable` concept has proven to be very useful when declaring and
1040 collecting SOAP Headers
for multiple services, which are collected into one
1043 ### Default member values
1045 Class and struct data members may be declared with a default initialization
1046 value that is provided "inline" with the declaration of the member:
1051 std::string name =
"Joe";
1053 These initializations are made by the
default constructor that is added by
1054 soapcpp2 to each
class and struct. A constructor is only added when a default
1055 constructor is not already defined with the class declaration.
1057 Initializations can only be provided for members that have primitive types
1058 (`bool`, `enum`, `time_t`, numeric and string types).
1060 ### Attribute members
1062 Class and struct data members can be declared as XML attributes by annotating
1063 their type with a `@` with the declaration of the member:
1073 This
class maps to a complexType in the soapcpp2-generated schema:
1075 <complexType name="record">
1077 <element name="spouse" type="ns:record" minOccurs="0" maxOccurs="1" nillable="true"/>
1079 <attribute name="name" type="xsd:string" use="required"/>
1080 <attribute name="SSN" type="xsd:unsignedLong" use="required"/>
1083 An example XML instance of `ns__record` is:
1085 <ns:record xmlns:ns="urn:types" name="Joe" SSN="1234567890">
1088 <SSN>1987654320</SSN>
1092 Attribute data members are restricted to primitive types (`bool`, `enum`,
1093 `time_t`, numeric and string types), `xsd__hexBinary`, `xsd__base64Binary`, and
1094 custom serializers, such as `xsd__dateTime`. Custom serializers for types that
1095 may be used as attributes MUST define `soap_s2T` and `soap_T2s` functions that
1096 convert values of type `T` to strings and back.
1098 Attribute data members can be pointers and smart pointers to these types, which
1099 permits attributes to be optional.
1101 ### (Smart) pointer members and their occurrence constraints
1103 A
public pointer-typed data member is serialized by following its (smart)
1104 pointer(s) to the value pointed to.
1106 Pointers that are NULL and smart pointers that are empty are serialized to
1107 produce omitted element and attribute values, unless an element is required
1110 To control the occurrence requirements of pointer-based data members,
1111 occurrence constraints are associated with data members in the form of a range
1112 `minOccurs : maxOccurs`. For non-repeatable (meaning, not a container or array)
1113 data members, there are only three reasonable occurrence constraints:
1115 - `0:0` means that this element or attribute is prohibited.
1116 - `0:1` means that this element or attribute is optional.
1117 - `1:1` means that this element or attribute is required.
1119 Pointer-based data members have a default `0:1` occurrence constraint, making
1120 them optional, and their XSD schema local element/attribute definition is
1121 marked as nillable. Non-pointer data members have a default `1:1` occurence
1122 constraint, making them required.
1124 A pointer data member that is explicitly marked as required with `1:1` will be
1125 serialized as an element with an xsi:nil attribute, thus effectively revealing
1126 the NULL property of its value.
1128 A non-pointer data member that is explicitly marked as optional with `0:1` will
1129 be set to its default value when no XML value is presented to the deserializer.
1130 A default value can be assigned to data members that have primitive types.
1132 Consider for example:
1137 std::shared_ptr<std::string> name;
1138 uint64_t SSN 0:1 = 999;
1139 ns__record *spouse 1:1;
1142 This
class maps to a complexType in the soapcpp2-generated schema:
1144 <complexType name="record">
1146 <element name="name" type="xsd:string" minOccurs="0" maxOccurs="1" nillable="true"/>
1147 <element name="SSN" type="xsd:unsignedLong" minOccurs="0" maxOccurs="1" default="999"/>
1148 <element name="spouse" type="ns:record" minOccurs="1" maxOccurs="1" nillable="true"/>
1152 An example XML instance of `ns__record` with its `name` string value set to
1153 `Joe`, `SSN` set to its default, and `spouse` set to NULL:
1155 <ns:record xmlns:ns="urn:types">
1158 <spouse xsi:nil="true"/>
1161 ### Container members and their occurrence constraints
1163 Class and struct data members declared as a container `std::deque`, `std::list`,
1164 `std::set`, and `std::vector` are serialized as a collection of values:
1169 std::vector<std::string> names;
1173 To practically limit the number of names within reasonable bounds, occurrence
1174 constraints are associated with the container. Occurrence constraints are of
1175 the form `minOccurs : maxOccurs`:
1180 std::vector<std::string> names 1:10;
1184 This
class maps to a complexType in the soapcpp2-generated schema:
1186 <complexType name="record">
1188 <element name="name" type="xsd:string" minOccurs="1" maxOccurs="10"/>
1189 <element name="SSN" type="xsd:unsignedLong" minOccurs="1" maxOccurs="1""/>
1193 Because C does not support a container template library, we can use a
1194 dynamically-sized array of values. This array is declared as a size-pointer
1204 where the marker `$` with `
int` denotes a special type that is used to store
1205 the array size and to indicate that
this is a size-pointer member pair that
1206 declares a dynamically-sized array.
1208 This
class maps to a complexType in the soapcpp2-generated schema:
1210 <complexType name="record">
1212 <element name="name" type="xsd:string" minOccurs="0" maxOccurs="unbounded" nillable="true"/>
1213 <element name="SSN" type="xsd:unsignedLong" minOccurs="1" maxOccurs="1""/>
1217 To limit the number of names in the array within reasonable bounds, occurrence
1218 constraints are associated with the array size member. Occurrence constraints
1219 are of the form `minOccurs : maxOccurs`:
1223 $int sizeofnames 1:10;
1228 This
class maps to a complexType in the soapcpp2-generated schema:
1230 <complexType name="record">
1232 <element name="name" type="xsd:string" minOccurs="1" maxOccurs="10" nillable="true"/>
1233 <element name="SSN" type="xsd:unsignedLong" minOccurs="1" maxOccurs="1""/>
1239 A union member in a class or in a struct cannot be serialized unless a
1240 discriminating variant selector is provided that tells the serializer which
1241 union field to serialize.
1243 The variant selector is associated with the union as a selector-union member
1244 pair, where the variant selector is a special `$int` member:
1259 The variant selector values are
auto-generated based on the
union name `choice`
1260 and the names of its members `x`, `n`, and `s`:
1262 - `xORnORs = SOAP_UNION_choice_x` when `u.x` is valid.
1263 - `xORnORs = SOAP_UNION_choice_n` when `u.n` is valid.
1264 - `xORnORs = SOAP_UNION_choice_s` when `u.s` is valid.
1265 - `xORnORs = 0` when none are valid (should only be used with great care,
1266 because XML content validation may fail when content is required but absent).
1268 This class maps to a complexType with a sequence and choice in the
1269 soapcpp2-generated schema:
1271 <complexType name="record">
1274 <element name="x" type="xsd:float" minOccurs="1" maxOccurs="1"/>
1275 <element name="n" type="xsd:int" minOccurs="1" maxOccurs="1"/>
1276 <element name="s" type="xsd:string" minOccurs="0" maxOccurs="1" nillable="true"/>
1278 <element name="names" type="xsd:string" minOccurs="1" maxOccurs="10" nillable="true"/>
1282 ### Adding get and set methods
1284 A
public `get` method may be added to a class or struct, which will be
1285 triggered by the deserializer. This method will be invoked right after the
1286 instance is populated by the deserializer. The `get` method can be used to
1287 update or verify deserialized content. It should return `SOAP_OK` or set
1288 `soap::error` to a nonzero error code and return it.
1290 A
public `set` method may be added to a class or struct, which will be
1291 triggered by the serializer. The method will be invoked just before the
1292 instance is serialized. Likewise, the `set` method should return `SOAP_OK` or
1293 set set `soap::error` to a nonzero error code and return it.
1295 For example, adding a `set` and `get` method to a class declaration:
1300 int set(
struct soap*);
1301 int get(
struct soap*);
1303 To add these and othe rmethods to classes and structs with wsdl2h and
1304 `typemap.dat`, please see section [
class and struct addition](#typemap3).
1306 ### Defining document root elements
1308 To define and reference XML document root elements we use type names that start
1313 Alternatively, we can use a typedef to define a document root element with a
1316 typedef ns__record _ns__record;
1318 This typedef maps to a global root element that is added to the
1319 soapcpp2-generated schema:
1321 <element name="record" type="ns:record"/>
1323 An example XML instance of `_ns__record` is:
1325 <ns:record xmlns:ns="urn:types">
1327 <SSN>1234567890</SSN>
1330 <SSN>1987654320</SSN>
1334 Global-level element/attribute definitions are also referenced and/or added to
1335 the generated schema when serializable data members reference these by their
1338 typedef std::string _ns__name 1:100;
1345 _ns__record *spouse;
1348 These types map to the following comonents in the soapcpp2-generated schema:
1350 <simpleType name=
"name">
1351 <restriction base=
"xsd:string">
1352 <minLength value=
"1"/>
1353 <maxLength value=
"100"/>
1356 <element name=
"name" type=
"ns:name"/>
1357 <complexType name=
"record">
1359 <element ref=
"ns:name" minOccurs=
"1" maxOccurs=
"1"/>
1360 <element name=
"SSN" type=
"xsd:unsignedLong" minOccurs=
"1" maxOccurs=
"1"/>
1361 <element name=
"spouse" type=
"ns:record" minOccurs=
"0" maxOccurs=
"1" nillable=
"true"/>
1363 <attribute ref=
"xsi:type" use=
"optional"/>
1365 <element name=
"record" type=
"ns:record"/>
1367 However, we must warn against
using qualified member names when their types
do
1368 not match their definitions:
1375 Therefore, we recommend to avoid qualified member names and only use them when
1376 referring to standard XSD elements and attributes, such as `xsi__type`, and
1377 `xsd__lang`. The soapcpp2 tool does not prevent abuse of
this mechanism.
1379 ### Operations on classes and structs
1381 The following functions/macros are generated by soapcpp2
for each type `T`,
1382 which should make it easier to send, receive, and copy XML data in C and in
1385 - `
int soap_write_T(
struct soap*, T*)` writes an instance of `T` to a FILE (via
1386 `FILE *soap::sendfd)`) or to a stream (via `std::ostream *soap::os`).
1387 Returns `SOAP_OK` on success or an error code, also stored in `soap->error`.
1389 - `
int soap_read_T(
struct soap*, T*)` reads an instance of `T` from a FILE (via
1390 `FILE *soap::recvfd)`) or from a stream (via `std::istream *soap::is`).
1391 Returns `SOAP_OK` on success or an error code, also stored in `soap->error`.
1393 - `
void soap_default_T(
struct soap*, T*)` sets an instance `T` to its
default
1394 value, resetting members of a
struct to their initial values (for classes we
1395 use method `T::soap_default`, see below).
1397 - `T * soap_dup_T(struct soap*, T *dst, const T *src)` (soapcpp2 option `-Ec`)
1398 deep copy `src` into `dst`, replicating all deep cycles and shared pointers
1399 when a managing soap context is provided as argument. When `dst` is NULL,
1400 allocates space for `dst`. Deep copy is a tree when argument is NULL, but the
1401 presence of deep cycles will lead to non-termination. Use flag
1402 `SOAP_XML_TREE` with managing context to copy into a tree without cycles and
1403 pointers to shared objects. Returns `dst` (or allocated space when `dst` is
1406 - `void soap_del_T(const T*)` (soapcpp2 option `-Ed`) deletes all
1407 heap-allocated members of this object by deep deletion ONLY IF this object
1408 and all of its (deep) members are not managed by a soap context AND the deep
1409 structure is a tree (no cycles and co-referenced objects by way of multiple
1410 (non-smart) pointers pointing to the same data). Can be safely used after
1411 `soap_dup(NULL)` to delete the deep copy. Does not delete the object itself.
1413 When in C++ mode, soapcpp2 tool adds several methods to classes and structs, in
1414 addition to adding a default constructor and destructor (when these were not
1415 explicitly declared).
1417 The
public methods added to a class/struct `T`:
1419 - `
virtual int T::soap_type(void)` returns a unique type ID (`SOAP_TYPE_T`).
1420 This numeric ID can be used to distinguish base from derived instances.
1422 - `
virtual void T::soap_default(struct soap*)` sets all data members to
1425 - `
virtual void T::soap_serialize(struct soap*) const` serializes object to
1426 prepare for SOAP 1.1/1.2 encoded output (or with `SOAP_XML_GRAPH`) by
1427 analyzing its (cyclic) structures.
1429 - `
virtual int T::soap_put(struct soap*, const char *tag, const char *type) const`
1430 emits object in XML, compliant with SOAP 1.1 encoding style, return error
1431 code or `SOAP_OK`. Requires `soap_begin_send(soap)` and
1432 `soap_end_send(soap)`.
1434 - `
virtual int T::soap_out(struct soap*, const char *tag, int id, const char *type) const`
1435 emits object in XML, with tag and optional id attribute and xsi:type, return
1436 error code or `SOAP_OK`. Requires `soap_begin_send(soap)` and
1437 `soap_end_send(soap)`.
1439 - `
virtual void * T::soap_get(struct soap*, const char *tag, const char *type)`
1440 Get object from XML, compliant with SOAP 1.1 encoding style, return pointer
1441 to object or NULL on error. Requires `soap_begin_recv(soap)` and
1442 `soap_end_recv(soap)`.
1444 - `
virtual void *soap_in(struct soap*, const char *tag, const char *type)`
1445 Get object from XML, with matching tag and type (NULL matches any tag and
1446 type), return pointer to object or NULL on error. Requires
1447 `soap_begin_recv(soap)` and `soap_end_recv(soap)`
1449 - `
virtual T * T::soap_alloc(void) const` returns a new object of type `T`,
1450 default initialized and not managed by a soap context.
1452 - `
virtual T * T::soap_dup(struct soap*) const` (soapcpp2 option `-Ec`) returns
1453 a duplicate of this object by deep copying, replicating all deep cycles and
1454 shared pointers when a managing soap context is provided as argument. Deep
1455 copy is a tree when argument is NULL, but the presence of deep cycles will
1456 lead to non-termination. Use flag `SOAP_XML_TREE` with managing context to
1457 copy into a tree without cycles and pointers to shared objects.
1459 - `
virtual void T::soap_del() const` (soapcpp2 option `-Ed`) deletes all
1460 heap-allocated members of this object by deep deletion ONLY IF this object
1461 and all of its (deep) members are not managed by a soap context AND the deep
1462 structure is a tree (no cycles and co-referenced objects by way of multiple
1463 (non-smart) pointers pointing to the same data).Can be safely used after
1464 `soap_dup(NULL)` to delete the deep copy. Does not delete the object itself.
1466 Special classes and structs {#toxsd10}
1467 ---------------------------
1469 A
class or struct with the following layout is a one-dimensional SOAP Array
1479 where `T` is the array element type. A multidimensional SOAP Array is:
1488 where `N` is the constant number of dimensions. The pointer points to an array
1489 of `__size[0]*__size[1]* ... * __size[N-1]` elements.
1491 A special
case of a one-dimensional array is used to define xsd:hexBinary and
1492 xsd:base64Binary types when the pointer type is `
unsigned char`:
1494 class xsd__hexBinary
1497 unsigned char *__ptr;
1503 class xsd__base64Binary
1506 unsigned char *__ptr;
1510 A
class or struct with a binary content layout can be extended to support
1511 MIME/MTOM (and older DIME) attachments, such as in xop:Include elements:
1517 unsigned char *__ptr;
1524 Attachments are beyond the scope of
this document and we refer to the gSOAP
1525 user guide
for more details.
1527 A
class or struct with the following layout is a complexType with simpleContent
1536 A wrapper
class/
struct may have any number of attributes declared with `@`.
1538 Memory management {#memory}
1541 Memory management with the `soap` context enables us to allocate data in
1542 context-managed heap space that can be collectively deleted. All deserialized
1543 data is placed on the context-managed heap by the gSOAP engine.
1545 Memory management in C {#memory1}
1546 ----------------------
1548 In C (wsdl2h option `-c` and soapcpp2 option `-c`), the gSOAP engine allocates
1549 data on a context-managed heap with:
1551 - `
void *soap_malloc(
struct soap*,
size_t len)`.
1553 The `soap_malloc`
function is a wrapper around `malloc`, but which also allows
1554 the `
struct soap` context to track all heap allocations for collective deletion
1555 with `soap_end(soap)`:
1560 struct soap *soap = soap_new();
1562 struct ns__record *record = soap_malloc(soap, sizeof(struct ns__record));
1563 soap_default_ns__record(soap, record);
1569 The soapcpp2 auto-generated deserializers in C use `soap_malloc` to allocate
1570 and populate deserialized structures, which are managed by the context for
1571 collective deletion.
1573 To make `char*` and `wchar_t*` string copies to the context-managed heap, we
1574 can use the functions:
1576 - `char *soap_strdup(struct soap*, const char*)` and
1578 - `wchar_t *soap_wstrdup(struct soap*, const wchar_t*)`.
1580 We use the soapcpp2 auto-generated `soap_dup_T` functions to duplicate data
1581 into another context (this requires soapcpp2 option `-Ec` to generate), here
1584 struct soap *other_soap = soap_new();
1585 struct ns__record *other_record = soap_dup_ns__record(other_soap, NULL, record);
1587 soap_destroy(other_soap);
1588 soap_end(other_soap);
1589 soap_free(other_soap);
1591 Note that the only reason to use another context and not to use the primary
1592 context is when the primary context must be destroyed together with all of the
1593 objects it manages while some of the objects must be kept alive. If the objects
1594 that are kept alive contain deep cycles then this is the only option we have,
1595 because deep copy with a managing context detects and preserves these
1596 cycles unless the `SOAP_XML_TREE` flag is used with the context:
1598 struct soap *other_soap = soap_new1(SOAP_XML_TREE);
1599 struct ns__record *other_record = soap_dup_ns__record(other, NULL, record);
1601 The resulting deep copy will be a full copy of the source data structure as a
1602 tree without co-referenced data (i.e. no digraph) and without cycles. Cycles
1603 are pruned and (one of the) pointers that forms a cycle is repaced by NULL.
1605 We can also deep copy into unmanaged space and use the auto-generated
1606 `soap_del_T()` function (requires soapcpp2 option `-Ed` to generate) to delete
1607 it later, but we MUST NOT do this for any data that we suspect has deep cycles:
1609 struct ns__record *other_record = soap_dup_ns__record(NULL, NULL, record);
1611 soap_del_ns__record(other_record);
1614 Cycles in the data structure will lead to non-termination when making unmanaged
1615 deep copies. Consider for example:
1624 Our code to populate a structure with a mutual spouse relationship:
1626 struct soap *soap = soap_new();
1628 struct ns__record pers1, pers2;
1629 soap_default_ns__record(soap, &pers1);
1630 soap_default_ns__record(soap, &pers2);
1632 pers1.SSN = 1234567890;
1633 pers1.spouse = &pers2;
1634 pers2.name = soap_strdup(soap,
"Jane");
1635 pers2.SSN = 1987654320;
1636 pers2.spouse = &pers1;
1638 struct ns__record *pers3 = soap_dup_ns__record(NULL, NULL, &pers1);
1639 struct ns__record *pers4 = soap_dup_ns__record(soap, NULL, &pers1);
1640 soap_set_mode(soap, SOAP_XML_TREE);
1641 struct ns__record *pers5 = soap_dup_ns__record(soap, NULL, &pers1);
1643 As we can see, the gSOAP serializer can serialize any heap, stack, or
static
1644 allocated data, such as in our code above. So we can serialize the
1645 stack-allocated `pers1` record as follows:
1647 soap->sendfd = fopen(
"record.xml",
"w");
1648 soap_set_mode(soap, SOAP_XML_GRAPH);
1649 soap_clr_mode(soap, SOAP_XML_TREE);
1650 soap_write_ns__record(soap, &pers1);
1651 fclose(soap->sendfd);
1652 soap->sendfd = NULL;
1654 which produces an XML document record.xml that is similar to:
1656 <ns:record xmlns:ns=
"urn:types" id=
"Joe">
1658 <SSN>1234567890</SSN>
1661 <SSN>1987654320</SSN>
1662 <spouse ref=
"#Joe"/>
1666 Deserialization of an XML document with a SOAP 1.1/1.2 encoded
id-ref graph
1667 leads to the same non-termination problem when we later
try to copy the data
1668 into unmanaged space:
1670 struct soap *soap = soap_new1(SOAP_XML_GRAPH);
1672 struct ns__record pers1;
1673 soap->recvfd = fopen(
"record.xml",
"r");
1674 soap_read_ns__record(soap, &pers1);
1675 fclose(soap->recvfd);
1676 soap->recvfd = NULL;
1678 struct ns__record *pers3 = soap_dup_ns__record(NULL, NULL, &pers1);
1679 struct ns__record *pers4 = soap_dup_ns__record(soap, NULL, &pers1);
1680 soap_set_mode(soap, SOAP_XML_TREE);
1681 struct ns__record *pers5 = soap_dup_ns__record(soap, NULL, &pers1);
1683 Copying data with `soap_dup_T(soap)` into managed space is always safe. Copying
1684 into unmanaged space requires diligence. But deleting unmanaged data is easy
1685 with `soap_del_T()`.
1687 We can also use `soap_del_T()` to
delete structures that we created in C, but
1688 only
if these structures are created with `malloc` and
do NOT contain pointers
1689 to stack and
static data.
1691 Memory management in C++ {#memory2}
1692 ------------------------
1694 In C++, the gSOAP engine allocates data on a managed heap
using a combination
1695 of `
void *soap_malloc(
struct soap*,
size_t len)` and `soap_new_T()`, where `T`
1696 is the name of a
class,
struct, or
class template (container or smart pointer).
1697 Heap allocation is tracked by the `struct soap` context for collective
1698 deletion with `soap_destroy(soap)` and `soap_end(soap)`.
1700 Only structs, classes, and class templates are allocated with `new` via
1701 `soap_new_T(struct soap*)` and mass-deleted with `soap_destroy(soap)`.
1703 There are four variations of `soap_new_T`
for class/
struct/
template type `T`
1704 that soapcpp2
auto-generates to create instances on a context-managed heap:
1706 - `T* soap_new_T(
struct soap*)` returns a
new instance of `T` with
default data
1707 member initializations that are
set with the soapcpp2
auto-generated `
void
1708 T::soap_default(
struct soap*)` method), but ONLY IF the soapcpp2
1709 auto-generated
default constructor is used that invokes `soap_default()` and
1710 was not replaced by a user-defined
default constructor.
1712 - `T* soap_new_T(
struct soap*,
int n)` returns an array of `n`
new instances of
1713 `T`. Similar to the above, instances are initialized.
1715 - `T* soap_new_req_T(
struct soap*, ...)` returns a
new instance of `T` and sets
1716 the required data members to the values specified in `...`. The required data
1717 members are those with minOccurs > 0, see the subsection on occurrence
1718 constraints in [Classes and structs](#toxsd9).
1720 - `T* soap_new_set_T(
struct soap*, ...)` returns a
new instance of `T` and sets
1721 the
public/serializable data members to the values specified in `...`.
1723 The above functions can be invoked with a NULL `soap` context, but we will be
1724 responsible to use `
delete T` to
remove this instance from the unmanaged heap.
1726 Primitive types and arrays of these are allocated with `soap_malloc` by the
1727 gSOAP engine. As we stated above, all types except
for classes, structs,
class
1728 templates (containers and smart pointers) are allocated with `soap_malloc`
for
1729 reasons of efficiency.
1731 We can use a C++
template to simplify the managed allocation and initialization
1732 of primitive values as follows (
this is
for primitive types only, because we
1733 should allocate structs and classes with `soap_new_T`):
1736 T* soap_make(struct soap *soap, T val)
1738 T *p = (T*)soap_malloc(soap,
sizeof(T));
1744 For example, assuming we have the following
class:
1754 We can instantiate a record by
using the
auto-generated
1755 `soap_new_set_ns__record` and our `soap_make` to create a SSN value on the
1758 soap *soap = soap_new();
1760 ns__record *record = soap_new_set_ns__record(
1763 soap_make<uint64_t>(soap, 1234567890),
1770 Note however that the gSOAP serializer can serialize any heap, stack, or
static
1771 allocated data. So we can also create a
new record as follows:
1773 uint64_t SSN = 1234567890;
1774 ns__record *record = soap_new_set_ns__record(soap,
"Joe", &SSN, NULL);
1776 which will be fine to serialize
this record as
long as the local `SSN`
1777 stack-allocated value remains in scope when invoking the serializer and/or
1778 using `record`. It does not matter
if `soap_destroy` and `soap_end` are called
1779 beyond the scope of `SSN`.
1781 To facilitate our
class methods to access the managing context, we can add a
1782 soap context pointer to a
class/
struct:
1792 The context is
set when invoking `soap_new_T` (and similar) with a non-NULL
1795 We use the soapcpp2
auto-generated `soap_dup_T` functions to duplicate data
1796 into another context (
this requires soapcpp2 option `-Ec` to generate):
1798 soap *other_soap = soap_new();
1799 ns__record *other_record = soap_dup_ns__record(other, NULL, record);
1801 soap_destroy(other_soap);
1802 soap_end(other_soap);
1803 soap_free(other_soap);
1805 To duplicate derived instances when a base
class instance is provided, use the
1806 auto-generated method `T* T::soap_dup(
struct soap*)`:
1808 soap *other_soap = soap_new();
1809 ns__record *other_record = soap_dup_ns__record(other_soap, NULL, record);
1811 soap_destroy(other_soap);
1812 soap_end(other_soap);
1813 soap_free(other_soap);
1815 Note that the only reason to use another context and not to use the primary
1816 context is when the primary context must be destroyed together with all of the
1817 objects it manages
while some of the objects must be kept alive. If the objects
1818 that are kept alive contain deep cycles then
this is the only option we have,
1819 because deep copy with a managing context detects and preserves these
1820 cycles unless the `SOAP_XML_TREE` flag is used with the context:
1822 soap *other_soap = soap_new1(SOAP_XML_TREE);
1823 ns__record *other_record = record->soap_dup(other_soap);
1825 The resulting deep copy will be a full copy of the source data structure as a
1826 tree without co-referenced data (i.e. no digraph) and without cycles. Cycles
1827 are pruned and (one of the) pointers that forms a cycle is repaced by NULL.
1829 We can also deep copy into unmanaged space and use the
auto-generated
1830 `soap_del_T()`
function or the `T::soap_del()` method (requires soapcpp2 option
1831 `-Ed` to generate) to
delete it later, but we MUST NOT
do this for any data
1832 that we suspect has deep cycles:
1834 ns__record *other_record = record->soap_dup(NULL);
1836 other_record->soap_del();
1837 delete other_record;
1839 Cycles in the data structure will lead to non-termination when making unmanaged
1840 deep copies. Consider
for example:
1849 Our code to populate a structure with a mutual spouse relationship:
1851 soap *soap = soap_new();
1853 ns__record pers1, pers2;
1855 pers1.SSN = 1234567890;
1856 pers1.spouse = &pers2;
1857 pers2.name =
"Jane";
1858 pers2.SSN = 1987654320;
1859 pers2.spouse = &pers1;
1861 ns__record *pers3 = soap_dup_ns__record(NULL, NULL, &pers1);
1862 ns__record *pers4 = soap_dup_ns__record(soap, NULL, &pers1);
1863 soap_set_mode(soap, SOAP_XML_TREE);
1864 ns__record *pers5 = soap_dup_ns__record(soap, NULL, &pers1);
1866 Note that the gSOAP serializer can serialize any heap, stack, or
static
1867 allocated data, such as in our code above. So we can serialize the
1868 stack-allocated `pers1` record as follows:
1870 soap->sendfd = fopen(
"record.xml",
"w");
1871 soap_set_mode(soap, SOAP_XML_GRAPH);
1872 soap_clr_mode(soap, SOAP_XML_TREE);
1873 soap_write_ns__record(soap, &pers1);
1874 fclose(soap->sendfd);
1875 soap->sendfd = NULL;
1877 which produces an XML document record.xml that is similar to:
1879 <ns:record xmlns:ns=
"urn:types" id=
"Joe">
1881 <SSN>1234567890</SSN>
1884 <SSN>1987654320</SSN>
1885 <spouse ref=
"#Joe"/>
1889 Deserialization of an XML document with a SOAP 1.1/1.2 encoded
id-ref graph
1890 leads to the same non-termination problem when we later
try to copy the data
1891 into unmanaged space:
1893 soap *soap = soap_new1(SOAP_XML_GRAPH);
1896 soap->recvfd = fopen(
"record.xml",
"r");
1897 soap_read_ns__record(soap, &pers1);
1898 fclose(soap->recvfd);
1899 soap->recvfd = NULL;
1901 ns__record *pers3 = soap_dup_ns__record(NULL, NULL, &pers1);
1902 ns__record *pers4 = soap_dup_ns__record(soap, NULL, &pers1);
1903 soap_set_mode(soap, SOAP_XML_TREE);
1904 ns__record *pers5 = soap_dup_ns__record(soap, NULL, &pers1);
1906 Copying data with `soap_dup_T(soap)` into managed space is always safe. Copying
1907 into unmanaged space requires diligence. But deleting unmanaged data is easy
1908 with `soap_del_T()`.
1910 We can also use `soap_del_T()` to
delete structures in C++, but only
if these
1911 structures are created with `
new` (and `
new []`
for arrays when applicable)
for
1912 classes, structs, and
class templates and with `malloc`
for anything
else, and
1913 the structures
do NOT contain pointers to stack and
static data.
1915 Features and limitations {#features}
1916 ========================
1918 There are several context initialization flags and mode flags to control XML
1919 serialization at runtime:
1921 - `SOAP_XML_STRICT`: strictly validates XML
while deserializing. Should not be
1922 used together with SOAP 1.1/1.2 encoding style of messaging.
1924 - `SOAP_XML_INDENT`: produces indented XML.
1926 - `SOAP_XML_CANONICAL`: c14n canonocalization, removes unnecessary `xmlns`
1927 bindings and adds them to appropriate places by applying c14n normalization
1928 rules. Should not be used together with SOAP 1.1/1.2 encoding style of
1931 - `SOAP_XML_TREE`: write tree XML without
id-ref, pruning data structure
1932 cycles to prevent nontermination.
1934 - `SOAP_XML_GRAPH`: write graph (digraph and cyclic graphs with shared pointers
1935 to objects)
using id-ref attributes. That is, XML with SOAP multi-ref
1936 encoded
id-ref elements. This is a structure-preserving serialization format,
1937 because co-referenced data and also cyclic relations are accurately represented.
1939 - `SOAP_XML_DEFAULTNS`: uses xmlns
default bindings, assuming that the schema
1940 element form is
"qualified" by
default (be warned
if it is not!).
1942 - `SOAP_XML_NOTYPE`: removes all xsi:type attribuation. This may affect the
1943 quality of the deserializer, which relies on xsi:type attributes to distinguish
1944 base
class instances from derived class instanced.
1946 - `SOAP_C_UTFSTRING`: enables all `std::string` and `char*` strings to
1947 contain UTF-8 content.
1949 Additional notes with respect to the wsdl2h and soapcpp2 tools:
1951 - Nested classes, structs, and typedefs in a gSOAP header file are unnested by
1954 - Use `#import "file.h"` instead of `#include` to import other header files in
1955 a gSOAP header file for soapcpp2. The `#include` and `#define` directives are
1956 accepted, but deferred to the generated code.
1958 - To remove any SOAP-specific bindings, use soapcpp2 option `-0`.
1960 - A gSOAP header file for soapcpp2 should not include any code statements, only
1961 data type declarations.
1963 - C++ namespaces are supported, use wsdl2h option `-qname`. Or add a `namespace
1964 name { ... }` to the header file, but the `{ ... }` MUST cover the entire
1965 header file content from begin to end.
1967 - Optional DOM support can be used to store mixed content or literal XML
1968 content. Otherwise, mixed content may be lost. Use wsdl2h option `-d`
for
1969 DOM support and compile and link with `dom.c` or `dom.cpp`.
1972 Removing SOAP namespaces from XML payloads {#nsmap}
1973 ==========================================
1975 The soapcpp2 tool generates a `.nsmap` file that includes two bindings
for SOAP
1976 namespaces. We can
remove all SOAP namespaces (and SOAP processing logic) with
1977 soapcpp2 option `-0` or by simply setting the two entries to NULL:
1979 SOAP_NMAC
struct Namespace namespaces[] =
1981 {
"SOAP-ENV", NULL, NULL, NULL},
1982 {
"SOAP-ENC", NULL, NULL, NULL},
1985 Note that once the `.nsmap` is generated, we can copy-paste the content into
1986 our project code. However,
if we rerun wsdl2h on updated WSDL/XSD files or
1987 `typemap.dat` declarations then we need to use the updated table.
1990 Examples {#examples}
1993 Select the project files below to peruse the source code examples.
1999 - `address.xsd` Address book schema
2000 - `address.cpp` Address book app (reads/writes address.xml file)
2001 - `addresstypemap.dat` Schema
namespace prefix name preference for wsdl2h
2002 - `graph.h`
Graph data binding (tree, digraph, cyclic graph)
2003 - `graph.cpp` Test graph serialization as tree, digraph, and cyclic
2009 - `address.h` gSOAP-specific data binding definitions from address.xsd
2010 - `addressStub.h` C++ data binding definitions
2011 - `addressH.h` Serializers
2012 - `addressC.cpp` Serializers
2013 - `address.xml` Address book data generated by address app
2014 - `graphStub.h` C++ data binding definitions
2015 - `graphH.h` Serializers
2016 - `graphC.cpp` Serializers
2017 - `
g.xsd` XSD schema with `
g:
Graph` complexType
2018 - `
g.nsmap` xmlns bindings namespace mapping table
2024 Building the AddressBook example:
2026 wsdl2h -
g -t addresstypemap.dat address.xsd
2027 soapcpp2 -0 -CS -I../../import -p address address.h
2028 c++ -I../.. address.cpp addressC.cpp -o address -lgsoap++
2030 Building the graph serialization example:
2032 soapcpp2 -CS -I../../import -p graph graph.h
2033 c++ -I../.. graph.cpp graphC.cpp -o graph -lgsoap++
2035 To compile without using the `libgsoap++` library: simply compile
2036 `stdsoap2.cpp` together with the above.
2041 To execute the AddressBook example:
2045 To execute the
Graph serialization example: