Remoting NG

Remoting NG WSDL/XML Schema Code Generator User Guide

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.

Figure 1: WSDL to C++ Code Generation
Figure 1: WSDL to C++ Code Generation

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.

options

This element contains elements that control code generation.

options/namespaceInSourceFileNames

If set to true, generated source file names include the full namespace, with the namespace components separated by an underscore. If set to false (default), source file names only contain the class name. This is helpful if there are multiple schema types with the same name, but in different namespaces.

options/namespaceInHeaderFileNames

If set to true, generated header file names include the full namespace, with the namespace components separated by an underscore. If set to false (default), header file names only contain the class name.

options/alwaysUseOptional

If set to true (default), Poco::Optional is used for elements with minOccurs of 0. This may lead to generated code that fails to compile due to circular header dependencies. The solution is to set this to false. In this case, Poco::Optional will only be used for scalar types and std::vector of scalar types. Poco::SharedPtr will be used for all other classes. This avoids circular header dependencies by using forward declarations in the generated headers.

options/generateAllBindings

If set to true, service classes for all bindings in the WSDL are generated. If set to false (default), only service classes for bindings referenced by services in the WSDL are generated. Setting this to true is required if the WSDL does not define any services.

options/useStdUtilities

If set to true, the code generator uses std::optional instead of Poco::Optional and std::shared_ptr instead of Poco::SharedPtr.

options/inlineAllMethods

If set to true, the code generator will inline all methods and not generate an implementation file. Defaults to false.

options/amalgamateSources

If set to true, the code generator will combine all generated implementation files into a single source file. This can greatly reduce compile times (and avoid other build issues) as only a single source file must be compiled instead of potentially hundreds for large schemas. See also amalgamatedSourceFileName. Defaults to false.

options/amalgamatedSourceFileName

This setting specifies the base name of the generated source file if the amalgamateSources option has been enabled. Defaults to Amalgamated.cpp. Note that the file extension is always set to .cpp.

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 (alternatively std::optional) or Poco::SharedPtr (alternatively std::shared_ptr), depending on option setting alwaysUseOptional. If set to true (default), Poco::Optional is used for all classes. If set to false, Poco::Optional is only used for scalar types (including std::string), or std::vector of scalar types.

Note that the generated code may fail to compile due to circular header dependencies if Poco::Optional is always used. In such a case, set alwaysUseOptional to false.

To have the code generator use std::shared_ptr instead of Poco::SharedPtr and std::optional instead of Poco::Optional, enable the useStdUtilities option.

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 fully supported. Code generation will succeed, but the resulting code may not compile, due to circular header file dependencies. Setting the alwaysUseOptional configuration setting to false may help to mitigate the issue if the A elements in B have minOccurs=0.

HTTPS Support

XSDGen can be built with support for downloading external schemas via HTTPS. This requires either OpenSSL or Schannel (on Windows). When building with CMake, HTTPS support will be automatically enabled if either the ENABLE_NETSSL or ENABLE_NETSSL_WIN option has been enabled.

When building with GNU Make, the POCO_XSD_ENABLE_HTTPS environment or Make variable must be defined to enable HTTPS support.

When building with the included Visual Studio project files, HTTPS support must be enabled by modifying the project settings. The POCO_XSD_ENABLE_HTTPS macro must be defined in the C/C++ > Preprocessor > Preprocessor Defines settings and the include search path for either the NetSSL_OpenSSL or NetSSL_Win library must be added (C/C++ > General > Additional Include Directories).

When run without command-line options, or with the --help (or /help) command-line option, XSDGen will print a notice about HTTPS support if it has been enabled.

Securely control IoT edge devices from anywhere   Connect a Device