[xsd-users] xs:choice representation in C++

Boris Kolpackov boris at codesynthesis.com
Mon Sep 28 10:11:07 EDT 2009


Hi Leonid,

Gershanovich, Leonid <leonid.gershanovich at 247realmedia.com> writes:

> I was wondering if you considered to use something like boost::variant 
> (http://www.boost.org/doc/libs/1_40_0/doc/html/variant.html) for mapping 
> xs:choice to c++.

Please see this post for some background on the possible choices when
mapping xs:choice (pun intended ;-)) to C++:

http://www.codesynthesis.com/pipermail/xsd-users/2007-March/000863.html


> It seems that representing following xsd construct:
> <xs:choice>
>   <xs:element name="stringEl" type="xs:string"/>
>   <xs:element name="intEl" type="xs:int"/>
> </xs:choice>
> 
> As
> typedef string stringEl_type;
> typedef int     intEl_type;
> 
> boost::variant < stringEl_type , intEl_type  > m_choicer;
> 
> Is little cleaner in terms of expressing intended object model than
> 
> optional < string > stringEl;
> optional < int > intEl;

True, though this approach will only work for some cases. Consider
the following:

 <xs:choice>
   <xs:element name="stringEl" type="xs:string"/>
   <sequence>
     <xs:element name="intEl" type="xs:int"/>
     <xs:element name="boolEl" type="xs:boolean"/>
   </sequence>
 </xs:choice>

Now the intEl and boolEl elements becomes a single choice arm. They
should be present or absent together. To handle this with variant you
will need to wrap them into a class. In other words, you will need to
start re-creating the compositor structure via C++ classes.

Speaking of re-creating the compositor structure, we have used this
approach in XSD/e for the C++/Hybrid mapping:

http://www.codesynthesis.com/products/xsde/c++/hybrid/

For your original choice example you will get something like this:

enum choice_arm_tag
{
  stringEl_tag,
  intEl_tag
};

choice_arm_tag
choice_arm () const;

void
choice_arm (choice_arm_tag);

// stringEl
//
const std::string&
stringEl () const;

std::string&
stringEl ();

void
stringEl (const std::string&);

// intEl
//
int
intEl () const;

int&
intEl ();

void
intEl (int);

See Section 4.4, "Compositors" in the C++/Hybrid Mapping Getting Started
Guide for more information:

http://www.codesynthesis.com/projects/xsde/documentation/cxx/hybrid/guide/#4.4


> class my_visitor : public boost::static_visitor<int>
> {
> public:
>     int operator()(intEl_type i) const
>     {
>         return i;
>     }
> 
>     int operator()(const stringEl_type & str) const
>     {
>         return str.length();
>     }
> };

>From my superficial look at boost::variant I gather that there are
two ways to extract the value: the visitor approach (which will be
way too heavy-weight for most use-cases) and the boost::get function
which doesn't really offer many advantages over what is possible now.
It sure is more awkward, thought.

BTW, if you are looking for a visitor way of traversing the object
model, have you seen the recent discussion on this topic? It starts
here:

http://www.codesynthesis.com/pipermail/xsd-users/2009-July/002391.html

Boris




More information about the xsd-users mailing list