I've been playing with gSOAP XML Data Binding and noticed that class generation varies depending on the XML schema style. 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: XML schema written in the Russian doll style
library.xsd (Russian doll style - generated 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 am using the following sequence in order 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 Russian doll styled XSD gSOAP generates classes with following design:
soapStub.h:
class SOAP_CMAC _ns1__library_book
{
public:
std::string isbn; /* required attribute */
...
};
class SOAP_CMAC _ns1__library
{
public:
std::vector<_ns1__library_book >book; /* required element of type ns1:library-book */
...
};
Note that _ns1__library
's member book
is implemented as vector of _ns1__library_book
objects. But this is not the case when we provide schema written in other styles where it is implemented as vector of pointers.
Case 2: XML schema written in the Venetian blind style
library.xsd (Venetian blind):
<?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; /* required attribute */
...
};
#endif
class SOAP_CMAC ns1__library_USCOREt
{
public:
std::vector<ns1__book_USCOREt * >book; /* required element of type ns1:book_t */
...
};
Case 3: XML schema written in the Sliced salami 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; /* required attribute */
...
};
#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 _ns1__library
's book collections member to be vector of objects - not a vector of pointers. I want to create instance of _ns1__book
on the stack and simply pass it (by reference) to vector's push_back()
. This is possible only for Russian doll-styled schemas.
How to force gSOAP to generate collection of elements member as vector of objects for any schema style? Shall some special arguments be provided to wsdl2h.exe and/or soapcpp2.exe? Shall XML schema document contain any additional elements?