[xsd-users] BUG in generated code: Custom list type's getDefaultValue() returns twice the number of elements as its defined fixed size

Boris Kolpackov boris at codesynthesis.com
Wed Feb 20 07:55:01 EST 2019


Delker, Stefan <Stefan.Delker at kmweg.de> writes:

>   <simpleType name="DISEntityType">
>     <restriction>
>       <simpleType>
>         <list itemType="unsignedShort"/>
>       </simpleType>
>       <length value="7" fixed="true"/>
>     </restriction>
>   </simpleType>
> 
>   <element name="entityType" type="DISEntityType" minOccurs="0" default="0 0 0 0 0 0 0"/>
>
> Our custom type implementation initializes the type by default having
> 7 elements, to guarantee all data is accessible:
>
> class DISEntityType : public DISEntityType_impl
> {
> public:
> 
>   DISEntityType () : DISEntityType_impl(DISEntityType_base(7, 0)) {}
>
>   inline uint32_t getKind() const { return uint32_t((*this)[0]); }
>
>   [...]
>
> }
> 
> From debugging the generated code, the default constructor already
> initializes the list with 7 elements.
>
> The _xsd_entityType_default_value_init () adds seven elements to the
> default constructed object using (7 times):
>
> {
>   ::xml_schema::UnsignedShort tmp (0U);
>   r.push_back (tmp);
> }
>
> Is this actually a bug or are we misusing some feature of XSD?

I believe the problem is in your mapping of the DISEntityType XML
Schema type to the DISEntityType C++ class. It does not reflect
what the schema says, which is, "a valid instance of DISEntityType
must contain 7 elements" (<length value="7" fixed="true"/>). It
does not say that "a valid instance of type DISEntityType always 
contains 7 zeroes". In particular, the following would be valid
per the schema definition of DISEntityType:

<element name="entityType2" type="DISEntityType" minOccurs="0" default="1 1 1 1 1 1 1"/>

In a sense, a more accurate mapping would have been something along
these lines:

class DISEntityType : public DISEntityType_impl
{
public:

  DISEntityType () {}

  inline uint32_t getKind() const
  {
    assert (size () == 7);
    return uint32_t((*this)[0]);
  }

  [...]
};

If you want to continue using your current mapping then one (admittedly
hackish) way to make it work would be to re-define push_back() (which
is pretty useless in your case anyway) along these lines:

class DISEntityType : public DISEntityType_impl
{
public:

  [...]
  
  inline void push_back (unsigned short x)
  {
    if (size () == 7)
      clear ();

    DISEntityType_impl::push_back (x);    
  }
};



More information about the xsd-users mailing list