[xsde-users] Using Type Mapping?
Boris Kolpackov
boris at codesynthesis.com
Thu Sep 11 05:33:50 EDT 2008
Hi Robert,
Robert Hammond <RobertH at microsol.ie> writes:
> Hi, I am trying to work my way through the "people" example to understand
> how the Type maps work properly.
>
> My assumption after reading the manual is that if I wanted to include my
> own type which was not in the schema file, that I could define it in a
> hxx file, include this and the parser would build the skeleton code for
> that type.
> Have I got this right?
Not exactly. For each type defined in XML Schema the XSD/e compiler
generates a parser skeleton. By default these parser skeletons don't
return anything from their post_*() functions.
You use type maps to tell the XSD/e compiler that a parser skeleton
corresponding to a particular schema type should return something.
Returning things from parser skeletons is useful when you need to
pass information from a "child" element/attribute parser to the
"parent" one. This is handy when, for example, you need to build
a custom in-memory representation of the data stored in XML.
Let's consider the gender type from the people example in the manual.
It is defined in XML Schema like so:
<xsd:simpleType name="gender">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="male"/>
<xsd:enumeration value="female"/>
</xsd:restriction>
</xsd:simpleType>
If we compile this schema fragment without specifying any type
maps then we get the following parser skeleton:
class gender_pskel: public xml_schema::string_pskel
{
public:
gender_pskel (xml_schema::string_pskel* base_impl);
virtual void
pre ();
virtual void
post_gender ();
};
As you can see, the post_gender() function returns void. This may be
perfectly sufficient if, for example, all you need to do is print the
gender value:
class gender_pimpl: public gender_pskel
{
public:
gender_pimpl ()
: gender_pskel (&base_impl_)
{
}
virtual void
post_gender ()
{
std::string s = post_string ();
cout << "gender: " << s << endl;
}
private:
xml_schema::string_pimpl base_impl_;
};
But what if you cannot process the gender value in gender_pimpl and
instead needed to pass the gender value to the "parent" parser, the
one generated for the person type:
<xs:complexType name="person">
<xs:sequence>
<xs:element name="gender" type="gender"/>
...
</xs:sequence>
</xs:complexType>
class person_pskel: public xml_schema::parser_complex_content
{
public:
virtual void
gender ();
...
};
One not very clean way would be to have a global variable that is set
in gender_pimpl and is examined in person_pimpl. Since passing data
from "child" parsers to "parent" parsers is a fairly common requirement,
XSD/e provides a mechanism for this. It allows you to specify, via
type maps, the return type of the "child" parser's post_*() function
(post_gender() in our case) and argument type of the "parent" parser's
callback (gender() in our case). The generated code is also responsible
for calling gender_pimpl::post_gender() and passing its return value
to person_pimpl::gender().
In our case we can create a C++ enum corresponding to the gender type
in XML Schema. We can place it, say, in gender.hxx:
enum gender
{
male,
female
};
We can then create a type map for our schema, people.map:
include "gender.hxx"
gender ::gender ::gender
In the second line the first identifier is of the schema type. The second
is the return type for gender_pimpl::post_gender() and the last one is the
argument type for the person_pimpl::gender() callback.
Once we compile our schema with this type map, the gender_pskel and
person_pskel skeletons change as follows:
#include "gender.hxx"
class gender_pskel: public xml_schema::string_pskel
{
public:
gender_pskel (xml_schema::string_pskel* base_impl);
virtual void
pre ();
virtual ::gender
post_gender ();
};
class person_pskel: public xml_schema::parser_complex_content
{
public:
virtual void
gender (::gender);
...
};
And our implementation could look like this:
class gender_pimpl: public gender_pskel
{
public:
gender_pimpl ()
: gender_pskel (&base_impl_)
{
}
virtual ::gender
post_gender ()
{
std::string s = post_string ();
return s == "male" : male ? female;
}
private:
xml_schema::string_pimpl base_impl_;
};
class person_pimpl: public person_pskel
{
public:
virtual void
gender (::gender g)
{
// g is the gender value returned by gender_pimpl.
}
};
Boris
More information about the xsde-users
mailing list