Introduction
XSDGen is a code generator that transforms XML Schema and WSDL files into C++ source code, annotated with Remoting attributes.
C++ code generation from an XML Schema or WSDL document is a two-step process. First, XSDGen parses the XML Schema or WSDL (and any referenced XML Schemas) and generates interface classes for the services, as well as classes for all complex types defined in the schema. Then, RemoteGenNG is used to generate the Remoting infrastructure code.
Figure 1 illustrates the code generation process from WSDL to C++ client code.
Configuring XSDGen
XSDGen requires an XML-based configuration file that tells the code generator where to put the generated header and implementation files, and how to map XML namespaces to C++ namespaces.
Sample Configuration
An example configuration file is shown below:
<AppConfig> <XSDGen> <default> <include>include/CheckVat</include> <src>src</src> <includeRoot>include</includeRoot> </default> <schema targetNamespace="urn:ec.europa.eu:taxud:vies:services:checkVat:types"> <include>include/CheckVat/Types</include> <namespace>CheckVat::Types</namespace> </schema> <schema targetNamespace="urn:ec.europa.eu:taxud:vies:services:checkVat"> <namespace>CheckVat</namespace> </schema> </XSDGen> </AppConfig>
The configuration file contains an XSDGen element, which in contains one default element containing default settings that apply to all schemas, unless explicitly overridden. It also contains a schema element for every target XML namespace used in the WSDL or XML Schema.
Configuration Elements
Following is a description of all XML elements supported in the configuration file.
AppConfig
The XML root or document element. The name of this element is not relevant. A typical element name is AppConfig, but any other valid element name would do as well.
XSDGen
This element is required. Its child elements contain the configuration data for the code generator.
default
This element is required. Its child elements contain the default settings that apply to all schema namespaces, unless explicitly overridden in the schema configuration.
schema
This element must be present for every XML target namespace defined in the WSDL or XML schema, as well as in referenced schemas. The code generator will abort if it encounters a namespace that does not have a corresponding schema element in the configuration file. The namespace must be specified in the targetNamespace attribute.
Each schema element should at least specify a unique C++ namespace for the schema's generated C++ classes, using the namespace element. Overriding the other default settings is optional.
namespace
This element is used to specify the C++ namespace for the C++ classes generated from types defined in the WSDL or XML Schema. Can be a nested namespace (e.g., Sample::Service).
Example:
<namespace>Sample::Service</namespace>
include
This element specifies the directory where header files for classes generated by the code generator are written to. The directory is automatically created if it does not already exist.
src
This element specifies the directory where implementation files for classes generated by the code generator are written to. The directory is automatically created if it does not already exist.
includeRoot
Specifies the base directory for all include files. This is required by the code generator to generate the paths for #include directives.
copyright
This specifies a copyright (or other) message that will be added to the header comment section of each generated header and implementation file.
library
If this element is specified, the code generated by the code generator is assumed to be exported from a (shared) library. For this to work with Windows DLLs, the classes must be defined with a __declspec directive. Specifying a library name will direct the code generator to create all class definitions in the form:
class Library_API Service { ... };
where Library in Library_API is replaced with the library name given in this element. For this to work, the Library_API macro must be defined somewhere.
The definition for this macro typically looks like this:
#if defined(_WIN32) && defined(POCO_DLL) #if defined(Library_EXPORTS) #define Library_API __declspec(dllexport) #else #define Library_API __declspec(dllimport) #endif #endif #if !defined(Library_API) #define Library_API #endif
alwaysInclude
This element instructs the code generator to always include the header file given as content.
Example:
<alwaysInclude>Sample/Service/Sample.h</alwaysInclude>
will instruct the compiler to include a
#include "Sample/Service/Sample.h"
directive in each header file it generates.
timestamps
Enable (default) or disable timestamps in generated C++ header and implementation files. Valid values are true to enable and false to disable timestamps. If enabled, every generated header and implementation file will include the date and time when the file was generated in its header comment block.
preserveOptional
This setting controls how XML elements defined in the Schema with both minOccurs="0" and nillable="true" are mapped to C++. If true is specified, the base type will be wrapped in both a Poco::Nullable and Poco::Optional class. For example an element:
<xsd:element name="aString" xsd:type="xsd:string" minOccurs="0" nillable="true"/>
will be mapped to:
Poco::Optional<Poco::Nullable<std::string> >
In most cases, this is not wanted, as it makes dealing with those types in code rather unpleasant. If false is specified for preserveOptional (which is the default), the element will simply be mapped to:
Poco::Nullable<std::string>
While it is no longer possible to distinguish between whether the element has been left out, or set to NIL (<aString xsi:nil="true">), this distinction is irrelevant in most cases.
Invoking XSDGen
Command Line Usage
The code generator is invoked by running the XSDGen executable.
When invoking XSDGen, the configuration file and the WSDL or XML Schema file must be passed as command line parameters. The configuration file is passed using the config option. The WSDL or XML Schema file is passed as normal argument.
For the WSDL or XML Schema file, either a local filesystem path or a URI can be specified. The URI can use the http or ftp schema, and XSDGen will download the file from the specified location.
On a Unix system, the code generator can be invoked with:
$ XSDGen --config=XSDGen.xml http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl
On a Windows system, the command syntax is slightly different:
C:\CheckVat> XSDGen /config=XSDGen.xml http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl
Command Line Options
XSDGen supports the following command line options:
- /help, --help, -h: Display help information on command line arguments.
- /config:<file>, --config=<file>, -c<file>: Load configuration from the given file specified by <file>.
Mapping Of XML Schema Types To C++
The following table shows how XML Schema types are mapped to C++ types.
XML Schema Type C++ Type --------------------------------------------------------- anySimpleType std::string anyType std::string (not supported) anyURI Poco::URI base64Binary std::vector<char> boolean bool byte Poco::Int8 date Poco::DateTime dateTime Poco::DateTime decimal double double double duration std::string ENTITIES std::string ENTITY std::string float float gDay std::string gMonth std::string gMonthDay std::string gYear std::string gYearMonth std::string hexBinary std::string ID std::string IDREF std::string IDREFS std::string int int integer int language std::string long Poco::Int64 name std::string NCName std::string negativeInteger Poco::Int32 NMTOKEN std::string NMTOKENS std::string nonNegativeInteger Poco::UInt32 nonPositiveInteger Poco::Int32 normalizedString std::string NOTATION std::string positiveInteger Poco::UInt32 QName std::string short Poco::Int16 string std::string time Poco::DateTime token std::string unsignedByte Poco::UInt8 unsignedInt Poco::UInt32 unsignedLong Poco::UInt64 unsignedShort Poco::UInt16
Elements with maxOccurs greater than 1 (or unbounded) are mapped to a std::vector of the base type.
Elements with minOccurs of 0 are mapped to Poco::Optional. Nillable elements are mapped to Poco::Nullable for scalar types, or Poco::SharedPtr for schema-defined complex types. If an element is nillable and also has minOccurs of 0, it will be mapped to Poco::Nullable, unless the preserveOptional configuration setting is set to true. In the latter case, it will be mapped to Poco::Optional<Poco::Nullable<baseType> >, or Poco::Optional<Poco::SharedPtr<baseType> >, respectively.
Nillable elements having a schema-defined complex type are mapped to Poco::SharedPtr.
Code Generator Limitations
When dealing with certain XML Schema and WSDL constructs, the code generator has the following restrictions.
WSDL Restrictions
- Only WSDL 1.1 is supported.
- Only Document/Literal Wrapped-style WSDL is supported. This is the most interoperable format and supported by all major SOAP implementations.
XML Schema Restrictions
- all is treated the same as sequence.
- choice: all elements will be wrapped in Poco::Optional, and it it the responsibility of the application to make sure exactly one element is specified.
- union is not supported. The code generator will abort with an exception.
- Simple types are handled in a simplified manner. If a simple type extends from another type and restricts it (e.g. to an integer with only two digits), we simply map the type to its parent. The client code is responsible for making sure the element's value corresponds to the restriction.
- Enumerations are simply treated as strings. The application is responsible for providing appropriate values that conform to the enumeration.
- anyType is not supported. Attributes and elements with type anyType will not be included in the generated C++ class and thus cannot be accessed from C++ code.
- Indirectly recursive data structures (e.g., class A has members of class B, which again has members of class A) are not supported. Code generation will succeed, but the resulting code will not compile, due to circular header file dependencies.