I played with gSOAP XML Data Binding and noticed that class generation varies depending on the style of the XML schema. Let me show you an example:
Library.xml
<?xml version="1.0" encoding="UTF-8"?> <library> <book isbn="0132350882"/> <book isbn="020161622X"/> <book isbn="0201633612"/> </library>
Case 1: An XML Schema Written in Russian Doll Style
library.xsd (Russian doll style created by Visual Studio 2010 from XML above):
<?xml version="1.0" encoding="utf-8"?> <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="library"> <xs:complexType> <xs:sequence> <xs:element maxOccurs="unbounded" name="book"> <xs:complexType> <xs:attribute name="isbn" type="xs:string" use="required" /> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
I use the following sequence to get proxy files (header and source):
c:\test\gSOAP_Test1>wsdl2h.exe -t "c:\tools\gsoap_2.8.6\gsoap-2.8\gsoap\typemap.dat" Library.xsd
c:\test\gSOAP_Test1>soapcpp2.exe -I "c:\tools\gsoap_2.8.6\gsoap-2.8\gsoap\import" Library.h
For a Russian doll XSD gSOAP generates classes with the following design:
soapStub.h
class SOAP_CMAC _ns1__library_book { public: std::string isbn; ... }; class SOAP_CMAC _ns1__library { public: std::vector<_ns1__library_book >book; ... };
Note that the _ns1__library member book is implemented as a vector of _ns1__library_book objects . But this is not the case when we provide a scheme written in other styles, where it is implemented as a vector of pointers .
Case 2: An XML Schema Written in the Style of a Venetian Nugget
library.xsd (blinds):
<?xml version="1.0" encoding="utf-8"?> <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:complexType name="book_t"> <xs:attribute name="isbn" type="xs:string" use="required"/> </xs:complexType> <xs:complexType name="library_t"> <xs:sequence> <xs:element name="book" type="book_t" minOccurs="1" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:element name="library" type="library_t"/> </xs:schema>
soapStub.h
class SOAP_CMAC ns1__book_USCOREt { public: std::string isbn; ... }; #endif class SOAP_CMAC ns1__library_USCOREt { public: std::vector<ns1__book_USCOREt * >book; /* required element of type ns1:book_t */ ... };
Case 3: An XML Schema Written in Salami Slicing Style
library.xsd (sliced ββsalami):
<?xml version="1.0" encoding="utf-8"?> <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="book"> <xs:complexType> <xs:attribute name="isbn" type="xs:string" use="required"/> </xs:complexType> </xs:element> <xs:element name="library"> <xs:complexType> <xs:sequence> <xs:element ref="book" minOccurs="1" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
soapStub.h
class SOAP_CMAC _ns1__book { public: std::string isbn; ... }; #endif class SOAP_CMAC _ns1__library { public: std::vector<_ns1__book * >ns1__book; /* required element of type ns1:book */ ... }
For the XML provided, I prefer the _ns1__library member of book collections to be an object vector rather than a pointer vector. I want to create an instance of _ns1__book on the stack and just pass it (by reference) to the push_back() vector. This is possible only for Russian puppet schemes.
How to make gSOAP generate a collection of elements as a vector of objects for any circuit style? Should there be any special arguments for wsdl2h.exe and / or soapcpp2.exe? Should the XML schema document contain any additional elements?