XML Binding Development Guide : PART III Advanced Topics : Chapter 8 Mapping XML Schema to C++ : Creating Customized Mappings
Creating Customized Mappings
HydraExpress enables you to customize the mapping of names, types and namespaces. HydraExpress’s default mapping settings, for example, map schema types string, date, and dateTime to the Standard C++ Library type std::string. You can customize this mapping so that these schema types instead map to your own C++ types.
To generate code that uses classes from SourcePro C++, simply use the ‑sourcePro command line option. SourcePro C++ contains classes that map naturally onto XML data types. For example, code generated with the -sourcepro option maps the schema types date and dateTime to the classes RWDate and RWDateTime. SourcePro C++ classes allow HydraExpress to create a convenient type-safe data binding without requiring a customized mapping configuration file. For a complete list of the SourcePro C++ type mappings, see Table 4.
To replace the mapping of all built-in schema types to your own C++ type, use the -datamap option at code generation, providing as an argument a configuration file containing a mappings element to identify the new mapping. Using the -datamap option results in an entirely new mapping of all schema types.
To customize the mapping of specific class names and types to your own C++ types, create a special HydraExpress project file containing the mappings element to specify the mapping, and then provide this file to the code generator at invocation. Alternatively, you may add the mappings element and its contents directly to an already-existing HydraExpress project file.
Customizing Names and Identifiers
HydraExpress provides the ability to customize the names that the code generator creates.
If you wish to customize names and identifiers for all code generation, use the ‑datamap command line option when generating code to provide the name of an XML-based file that defines the new names.
If you wish to customize names and identifiers for specific instances, create a project file containing a mappings element and provide this to the code generator. This is the procedure described in this section.
A HydraExpress project file is XML. The root element of all HydraExpress project files is named rwsf-codegen-project. (See “The Project File,” in the HydraExpress Web Service Development Guide for more information.) In this case, it will contain a single mappings element. The mappings element may contain any number of name elements. Each name element declares a rule for HydraExpress to use when creating identifiers.
Each name element contains three required and one optional attribute:
xsdname — the name that appears in the schema
xsdtype — the type of definition the mapping applies to. This attribute may have a value of element, attribute, complexType or all.
name — the name HydraExpress uses in the generated code
namespace — the namespace in which the element, attribute, or complexType is defined. This attribute is optional.
The HydraExpress project file below defines three name mappings:
 
<rwsf-codegen-project project-name="CustomMappings">
<mappings>
<name xsdname="recipientAddress"
xsdtype="element" name="ToAddress"/>
<name xsdname="address"
namespace="http://www.standardletters.com/address2"
xsdtype="complexType" name="AltAddress"/>
<name xsdname="body" xsdtype="all" name="LetterBody"/>
</mappings>
</rwsf-codegen-project>
The first name mapping specifies that HydraExpress will use the name ToAddress in code generated for an element named recipientAddress. Note that the mapping applies only to elements. Attributes or complex types with the name recipientAddress are not affected by this rule.
The second name mapping specifies that HydraExpress will use the name AltAddress in code generated for a complex type named address within the http://www.standardletters.com/address2 namespace.
The third name mapping specifies that HydraExpress will use the name LetterBody for any element, attribute, or complex type with a name of body.
Note that for complexType and element definitions that contain anonymous type definitions, the name mapping specifies the name of the accessor and mutator as well as the class name. Mapping rules that match element and attribute names in declarations within a complexType definition only affect the names of the get and set methods, since HydraExpress does not create classes for these declarations.
The mapping can also specify a full C++ class name under the xsdname attribute, and any classes that end up with the given name (based on the naming rules in “Names and Identifiers”) will have their class names (and any associated accessors) remapped.
Flexible Type Mapping
The 44 built-in schema types are mapped to C++ types using the default mapping shown in Table 4. You can map any of these schema types to a C++ type of your choice. In order to provide this mapping flexibility, HydraExpress requires the following information:
code to convert to and from a standard std::string instance
NOTE >> The HydraExpress internal parser, rwsf::XmlReader, uses std::string instances to hold content before converting to the type specified by the datamap. Therefore, your custom types must provide a way to convert to and from std::string. See the example below for an illustration of how to do this.
a value to use as a default value
an indication of how to construct an instance of your chosen type given a default value specification in an XML Schema
user-defined types require one additional attribute:
The include attribute specifies the header file for the user-defined type. The attribute must contain any path information necessary for the compiler to locate the file.
Here is an example HydraExpress project file that maps xsd:string, xsd:date, xsd:dateTime, xsd:time, xsd:integer and xsd:duration to std::string.
 
<rwsf-codegen-project project-name="CustomMappings">
<mappings>
<type xsdType="string" cppType="std::string"/>
<type xsdType="date" cppType="std::string"/>
<type xsdType="dateTime" cppType="std::string"/>
<type xsdType="time" cppType="std::string"/>
<type xsdType="duration" cppType="std::string"/>
<type xsdType="integer" cppType="std::string"/>
<typeinfo cppType="std::string" include="string">
<fromString>std::string($value$)
</fromString>
<toString>std::string($value$)
</toString>
<defaultValue>std::string("$value$")</defaultValue>
<initialValue></initialValue>
</typeinfo>
</mappings>
</rwsf-codegen-project>
A type element defines a mapping between an XML Schema type and a C++ type. Each type element must contain an xsdType attribute and a cppType attribute. The xsdType attribute defines the XML Schema type the mapping applies to. The cppType attribute defines the C++ type that HydraExpress generates for the XML Schema type.
Each cppType must be defined in a typeinfo element. The typeinfo element provides the information that HydraExpress needs to successfully generate code for the cppType. You may specify the following attributes and child elements for the typeinfo element.
cppType attribute – This is required and must match exactly with the cppType attribute value from the type mapping element.
include attribute – This is required and provides the include filename so the type definition is available to the generated usage of it. The value may be empty (include="") if not relevant, but the attribute must be present.
isPrimitive attribute – This is optional and specifies that the type is primitive (bool, int, double, etc...)
fromString element – Provides the logic to convert from an std::string instance to the user specified type. The $value$ parameter represents the std::string variable that needs to be operated on.
toString element – Provides the logic to convert from the user specified type to an std::string instance. The $value$ parameter represents the user defined type instance that needs to be converted to an std::string.
defaultValue element – Provides the logic to construct a valid user specified type instance from a default value specified in a schema. This is the unquoted literal, extracted from the default attribute in the XML Schema. Note that if the literal needs to be quoted, you must include the quotes in this element value.
initialValue element – Whatever is provided for this element is used in the default constructor to initialize all members of this user specified type.
Namespace Mapping
By default, HydraExpress creates classes in a C++ namespace with the same name as the namespace prefix for the XML Schema type. You can customize this behavior to specify a different value to use for the C++ namespace, as well as an XML prefix that is independent of the C++ namespace.
Customizing the C++ Namespace
In the configuration file, use the namespace element’s attribute name to specify the mapping from the namespace URI to the C++ namespace.
The sample below maps the namespace URI http://www.roguewave.com/remap to the C++ namespace CustomNamespace:
 
<rwsf-codegen-project project-name="NamespaceMappingToCPlusPlus">
<mappings>
<namespace uri="http://www.roguewave.com/remap"
name="CustomNamespace"/>
</mappings>
</rwsf-codegen-project>
With this file, HydraExpress maps all elements in the namespace http://www.roguewave.com/remap to classes in the C++ namespace CustomNamespace, regardless of the prefix associated with http://www.roguewave.com/remap in the schema.
If the name attribute is present but empty (i.e. name=""), HydraExpress will use the default mapping.
Customizing the XML Prefix in XML Instance Documents
You can also specify a prefix to be used when marshaling your C++ objects back to XML documents. This may be useful, for instance, if you wish to retain characters in your XML document prefix that are invalid in C++. You can also choose to generate XML instance documents with no prefix at all, useful to avoid unnecessary bloat in very large documents.
Use the prefix attribute on the namespace element to specify a value for your XML prefix.
The sample below marshals the namespace for all C++ objects to an XML prefix CustomPrefix regardless of the prefix associated with http://www.roguewave.com/remap in the schema.
 
<rwsf-codegen-project project-name="NamespaceMappingToXml">
<mappings>
<namespace uri="http://www.roguewave.com/remap"
prefix="CustomPrefix"/>
</mappings>
</rwsf-codegen-project>
Alternatively, you could assign no prefix to indicate that the default namespace should be used:
 
<rwsf-codegen-project project-name="NamespaceMappingToXml">
<mappings>
<namespace uri="http://www.roguewave.com/remap"
prefix=""/>
</mappings>
</rwsf-codegen-project>
Note that overriding the C++ namespace using only the name attribute customizes it for both the C++ namespace and the XML namespace prefix.
String Mapping
When the mappings element contains a user-specified type for xsd:string, the generated classes use the specified string type wherever a class requires a string. The exception to this rule is the marshaling methods, which do the following:
The marshal() method signatures use the base string type, which is std:string for code generated with the -stl option, and RWCString for code generated with the -sourcepro option.
The unmarshal() method signatures have one overload that uses the base string type, and one overload that uses the specified string type.