About generated source

The doxygen documentation

You should generate doxygen documentation for the generated code from your XML-Schema while going through this documentation.

In the output directory, run:
$ make doxygen-doc

The html documentation is generated in doc/html path relative to the output directory. Open doc/html/index.html in the browser of your choice, to read the documentation.

Namespaces

Understanding namespaces of the generated source

The C++ type-definition for each schema-component has two namespaces: The directory...namespace and CPP...namespace have standard one-to-one mapping. For example C++ namespace org:engg maps to directory namespace org/engg. So, a class with org::engg C++ namespace would have it's C++ header file(.h) in include/org/engg/ directory, and it's source file(.cpp) in src/org/eggg/ directory.

For sake of namespace undertanding, the schema-components should be divided into two categories:
  1. top-level declaration/definition
    The namespace of the C++ type definition(both directory and C++ namespaces) for top-level elements/attributes, are derived from the targetNamespace of the Schema. If targetNamespace is absent in the XML-Schema then "urn:NoNS" is considered as the implicit targetNamespace, for C++ type definitions only.
    The namespace of the C++ type definition for a top-level simpleType/complexType, is further augmented by a fixed namespace"Types".

    For instance, the C++ type-definition of a top-level element/attribute in a XML-Schema with targetNamespace="urn:org:engg" lies in a directory path(relative) org/engg with the C++ namespace urn::org::engg. While the C++ type-definition for a simpleType/complexType in the same XML-Schema, lies in a directory path org/engg/Types with the C++ namespace org::engg::Types.

  2. declaration/definition inside a parent element
    In this case the C++ type definition lies as an inner Class inside the C++ type definition class of the parent Schema element.

Directory structure of source generated in output directory named OD
directory file about contents
OD/ (output directory)
  • main.cpp
  • Makefile.am, configure.ac and other automake related files
  • the template main.cpp
  • automake related files
OD/include/ Makefile.am for Makefile
OD/include/directory...namespace/
  • Document.h
  • <element-name>.h
  • attr_<attribute-name>.h
  • all-include.h
header files from input-schema(or included/imported docs)
  • Document class inside Document.h
  • header files defining C++ classes for each top-level element declarations
  • header files defining C++ classes for each top-level attribute declarations
  • other misc headers like all-include.h
OD/include/directory...namespace/Types/
  • <simpleType-name>.h
  • <complexType-name>.h
header files from input-schema(or included/imported docs)
  • header files defining C++ classes for each top-level simpleType declarations
  • header files defining C++ classes for each top-level complexType declarations
OD/src/ Makefile.am for Makefile
OD/src/directory...namespace/
  • Document.cpp
  • <element-name>.cpp
  • attr_<attribute-name>.cpp
source(.cpp) files from input-schema(or included/imported docs):
  • Source file for Document class in file Document.cpp
  • Source files(.cpp) for each top-level element declarations
  • Source files(.cpp) for each top-level attribute declarations
OD/include/directory...namespace/Types/
  • <simpleType-name>.cpp
  • <complexType-name>.cpp
source(.cpp) files from input-schema(or included/imported docs):
  • Source files(.cpp) for each top-level simpleType declarations
  • Source files(.cpp) for each top-level complexType declarations




Currently XmlPlus supports two types of URI in target-namespace: Refer to following table to know how target-namespace(s) of the XML-Schema(s) map to directory...namespace and CPP...namespace, in the generated code context.

XML-Schema target-namespace-uri to implementation namespace mapping
target namespace of the XML-Schema directory...namespace ie. directory nesting CPP...namespace ie. C++ namespace nesting
http://www.example.com/org/engg http_www_example_com_org_engg http_www_example_com_org_engg
urn:org:engg org/engg org::engg
no targetNamespace
(implicit targetNamespace as "urn:NoNS")
NoNS NoNS


Obviously, the an URL mapped to directory/C++-namespace such as "http_www_example_com_org_engg", seems unfriendly from programming perspective.
There is a solution to this scenario. Before generating C++ code using xsd2cpp, create a file named nsaliases.xml in the same path as that of the XML-Schema file. This xml file should provide mappings for target-namespace URLs of your XML-Schema(s) to coresponding URNs of your choice.
<nsaliases>
   <alias uri="target-namespace-url1" toUrn="urn:urn1"/>
   <alias uri="target-namespace-url2" toUrn="urn:urn2"/>
   <alias uri="target-namespace-url3" toUrn="urn:urn3"/>
   ...
   ....
</nsaliases>

Following is an example of such a nsaliases.xml file:
<nsaliases>
  <alias uri="http://www.example.com/org"             toUrn="urn:org"/>
  <alias uri="http://www.example.com/org/engg"    toUrn="urn:org:engg"/>
</nsaliases>

Such a nsaliases.xml file would map URL "http://www.example.com/org/engg" to an URN "urn:org:engg", only for determining implementation namespace during C++ code generation phase . The implementation namespace is used in deciding directory structure as well as C++ namespaces for the generated C++ classes. The mapping created by nsaliases.xml, does not impact the target-namespace of the elements/attributes while reading/writing XML files.

Namespaces of the elements and attributes in the XML instance document

XML-Namespace of an element/attribute in a valid instance XML document, is based on the XML-Schema specification. An implementation like XmlPlus has no semantics to add here.
If the XML-Schema, and the imported Documents, have no targetNamespace specified, then none of elements/attributes in the instance XML document would have a namespace URI. Otherwise, some elements/attributes in the instance XML document would have a namespace URI. Even in the later case, not all elements/attributes in the instance XML document would have a namespace URI.
If a non-ref element/attribute does have a XML-Namespace, the namespace URI would be the targetNamespace URI of the XML-Schema document in which the element/attribute appears.
For ref element/attribute, it would be the namespace-uri for the element/attribute being referred to.

Whether an element/attribute in the instance XML document of a XML-Schema, should or should not have a namespace, depends on following:
Decision Table for Namespaces of the element(non-ref) in the XML instance document
target-namespace-uri present in the XML-Schema ? is top-level ? form ? namespace-uri of the element in the instance document
no DONT CARE DONT CARE
(none)
yes yes DONT CARE
target-namespace-uri of the containing Schema
yes no qualified
target-namespace-uri of the containing Schema
yes no unqualified
(none)


Decision Table for Namespaces of the attributes(non-ref) in the XML instance document
target-namespace-uri present in the XML-Schema ? is top-level ? form ? namespace-uri of the attribute in the instance document
no DONT CARE DONT CARE
(none)
yes yes DONT CARE
target-namespace-uri of the containing Schema
yes no qualified
target-namespace-uri of the containing Schema
yes no unqualified
(none)


Naming of the C++ Classes corresponding to the XML-Schema components

Folowing table enumerates different C++ types for schema-components(elements/attributes/simpleType/complexType etc.).
Note that the namespace (directory..namespace and CPP...namespace) corresponding to the targetNamespace of the XML-Schema is prepended to the respective types, and are ommitted here for sake of simplicity.
Naming and Namespaces
Annotation component's position in the tree component's C++ Type, pointer and Smart pointer
top-level element
  <schema>
    <element name="myElement" type="MyElemType"/>
    ...
    ....
  </schema>
  • myElement
  • myElement* or myElement_p
  • AutoPtr<myElement> or myElement_ptr
top-level attribute
  <schema>
    <attribute name="MyAttr" type="MyAttrType"/>
    ...
    ....
  </schema>
  • myAttr
  • myAttr* or myAttr_p
  • AutoPtr<myAttr> or myAttr_ptr
top-level Type
  <schema>
    ...

    <complexType name="MyComplexType" >
      ...
    </complexType>

    ...
  </schema>
  • MyComplexType
  • MyComplexType* or MyComplexType_p
  • AutoPtr<MyComplexType> or MyComplexType_ptr
local element
  <schema>
    <element name="element1" ...>
      ...
      <element name="element2" ...>
        ...
        <element name="myElement type="MyElemType"/>
        ...
      </element>
      ...
    </element>
  </schema>
        
  • element1::element2::myElement
  • element1::element2::myElement*
    or
    element1::element2::myElement_p
  • element1::element2::myElement_ptr
    or
    element1::element2::myElement_ptr
local attribute
  <schema>
    <element name="element1" ...>
      ...
      <element name="element2" ...>
        ...
        <attribute name="myAttr" type="MyAttrType"/>
        ...
      </element>
      ...
    </element>
  </schema>
  • element1::element2::myAttr
  • element1::element2::myAttr*
    or
    element1::element2::myAttr_p
  • AutoPtr<element1::element2::attr_myAttr>
    or
    element1::element2::attr_myAttr_ptr
nested(anonymous) Type -- you should not need to know, as the anonymous type would be wrapped inside an element/attribute or a top-level Type, and you would only need access to them


simpleType to implementation-type mapping

This C++ data-binding mapping for XML Schema simpleTypes, is available in excel file xsd.xls inside html_docs/files directory.
Open this file and view the tab named "XSD_Builtiin_DataTypes".

Understanding API


Using following notations while discusisng the APIs In the XML-Schema an element is often a composition of other elements/attributes. The composition of child-attributes is straightforward, that is child-attributes are specified as direct children of the parent-element.

However, the child-elements are composed through many abstractions:

  parent-element


Following sections describe the various relevant APIs:



The main.cpp file

The xsd2cpp tool generates a main.cpp in the output directory. The main.cpp is a demo application. It serves the purpose of showing:
a) how the build of generated source(libraries and headers), are to be consumed
b) all uses cases possible, and their HOWTOs.

This main.cpp common functions are placed inside src/XSD/UserOps.cpp relative to XmlPlus source-root. The main() function of the generated main.cpp, calls XSD_USER_OPS::xsd_main(), to use those funtions, which in turn callback the template functions, which user needs to fill code with.
Your application does not have to use these utility functions, if you don't want to. There is an unfolded main.cpp available under examples/simplest/main.cpp, which does not use the utility functions and callback mechanism like stated before. Refer to examples/simplest/main.cpp for such a need.

In the generated main.cpp, you may need to write code in some template functions:
  1. chooseDocumentElement() : to choose the documentElement ie root of the document.
    The options would be already available, you just need to uncomment the appropriate line. This callback function is available, when there are more than one top-level elements in the source(or included/imported) document(s).

  2. populateDocument() : to populate the Document while writing a fresh XML file
    Write code populate the document with values, starting from root.

  3. updateOrConsumeDocument() : callback function where you could test the Document, consume the Document or update the Document, in the -u option(read,operate,write). If this function is not filled, then the -u option is as good as -r option.
For writing sample XML document, roundtripping XML document, or validating XML document you don't have to fill the 2) and 3) in the above mentioned item list.

A relevant sample code-snippet of main.cpp follows:
 // Following functions are use case templates.
 // You need to put "code" in the respective contexts.
 //

 void chooseDocumentElement(STDemo::Document* xsdDoc)
 {
     // uncomment one of folowing to choose root
     xsdDoc->set_root_myComplexTypeElem();
     //xsdDoc->set_root_intValue2();
 }

 void populateDocument(DOM::Document* pDoc)
 {
     STDemo::Document* docNode = dynamic_cast<STDemo::Document *>(pDoc);
     // write code to populate the Document here
     ...
     ....
     rootElem->set_aFont("medium");
     rootElem->set_anotherFont("72");
     ....
     ...
 }

 void updateOrConsumeDocument(DOM::Document* pDoc)
 {
     STDemo::Document* xsdDoc = dynamic_cast<STDemo::Document *>(pDoc);
     // write code to update the populated-Document here
 }
    


Use Cases with generated source

One should go through XmlPlus examples to understand how an application can consume code generated from xsd2cpp tool.
Following are some use cases.