[xsd-users] C++/Parser: string extension

Boris Kolpackov boris at codesynthesis.com
Mon Oct 23 03:01:52 EDT 2006


Hi Robert,

Boucher, Robert J <Robert.Boucher at ca.com> writes:

> I have encountered difficulty in correctly using XSD for parsing a
> schema that extends the built-in string data type.  For example, I
> replaced the type of the element "name" in the hello.xsd sample with
> "stringWithType" which simply adds an attribute "type".
>
> ...
>
>     <xsd:complexType name="stringWithType">
>         <xsd:simpleContent>
>             <xsd:extension base="xsd:string">
>                 <xsd:attribute name="type" type="xsd:string" />
>             </xsd:extension>
>         </xsd:simpleContent>
>    </xsd:complexType>
>
> ...
>
> When I try to create a parser using this schema, and implement the
> parser for stringWithType, I can capture the type value, when present,
> but I cannot capture the value of the actual element.  On the otherhand,
> if I configure the hello_type to use the standard string parser for
> stringWithType, I get the value but obviously not the attribute.

The way to implement a parser for this type is to derive from the
standard string parser. It also gets a bit tricky because the return
types of the base parser (xml_schema::string) and the derived one
are not covariant. Because of that we will need to do it in two
steps: in the first step we 'rename' one of the post functions:


struct stringWithTypeParserBase: stringWithType<myStringWithType,
                                                std::string> // type
{
  virtual myStringWithType
  post_string_with_type () = 0;

  virtual myStringWithType
  post ()
  {
    return post_string_with_type ();
  }
};

Here stringWithType is the generated parser template and myStringWithType
is a type that captures the result of parsing; you can use 'void' instead
of it if you are not returning anything. The second step is to implement
the parser itself:

struct stringWithTypeParser: stringWithTypeParserBase,
                             xml_schema::string
{
  virtual void
  pre ()
  {
    xml_schema::string::pre ();
    type_.clear ();
  }

  virtual void
  type (const std::string& t)
  {
    type_ = t;
  }

  virtual myStringWithType
  post_string_with_type ()
  {
    return myStringWithType (xml_schema::string::post (), type_);
  }

private:
  std::string type_;
};

The reason why we need this two steps is because if we were to override
the post() member function in stringWithTypeParser we would end up with
a conflict because there are two virtual functions that can be overridden:
one from stringWithType with signature:

myStringWithType post ();

And the other is from xml_schema::string with signature:

std::string post ();

Since their return types are not covariant we cannot override both of them
with one function. There is the mix-in example in the examples/cxx/parser
directory which shows various methods of re-using parsers via derivation,
including this one. Also this technique is used in the library example
where the title type is derived from string and also has the lang
attribute.


hth,
-boris
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 652 bytes
Desc: Digital signature
Url : http://codesynthesis.com/pipermail/xsd-users/attachments/20061023/52d80066/attachment.pgp


More information about the xsd-users mailing list