Skip to content

kdwsdl2cpp: maxOccurs ignored on xs:element inside xs:choice #308

@KrissN

Description

@KrissN

I'm working on accessing the Microsoft Exchange Web Services (EWS) SOAP API using KDSoap. I have parsed the schema downloaded from the server (attached for reference), but I'm getting some incorrect code generated by kdwsdl2cpp:

The interesting XML element snippet from types.xsd (line 1190):

<xs:complexType name="NonEmptyArrayOfPropertyValuesType">
  <xs:choice>
    <xs:element name="Value" type="xs:string" maxOccurs="unbounded"/>
  </xs:choice>
</xs:complexType>

This element occurs inside an item request, where extended properties are requested. Some of them can hold a single value, while other - hold a list of values. The above type handles the latter case. An example server response may look like this:

<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <h:ServerVersionInfo MajorVersion="15" MinorVersion="20" MajorBuildNumber="8534" MinorBuildNumber="27" Version="V2018_01_08" xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
  </s:Header>
  <s:Body>
    <m:GetFolderResponse xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
    <m:ResponseMessages>
      <m:GetFolderResponseMessage ResponseClass="Success">
        <m:ResponseCode>NoError</m:ResponseCode>
        <m:Folders>
          <t:Folder>
            <t:FolderId Id="c/5dBIB1LMxCYYZa4VzJ7g=" ChangeKey="9HpuJZFo7/lxzdpUpheeJQ="/>
            <t:DisplayName>Top of Information Store</t:DisplayName>
            <t:ExtendedProperty>
              <t:ExtendedFieldURI PropertySetId="9bf757ae-69b5-4d8a-bf1d-2dd0c0871a28" PropertyName="GlobalTags" PropertyType="StringArray"/>
              <t:Values>
                <t:Value>Jp5sowSC5qdKm4QPvHabxw=</t:Value>
                <t:Value>KJ3NaVb9SJzsRfhb+e3HfA=</t:Value>
                <t:Value>l4FpfBj5qcs1XJcJ2Qpp1w=</t:Value>
                <t:Value>cpYaRsQC424fjlj/OE/asw=</t:Value>
              </t:Values>
            </t:ExtendedProperty>
            <t:ExtendedProperty>
              <t:ExtendedFieldURI PropertySetId="9bf757ae-69b5-4d8a-bf1d-2dd0c0871a28" PropertyName="GlobalTagsVersion" PropertyType="Integer"/>
              <t:Value>787</t:Value>
            </t:ExtendedProperty>
          </t:Folder>
        </m:Folders>
      </m:GetFolderResponseMessage>
    <m:ResponseMessages>
  </s:Body>
</s:Envelope>

The problem is that kdwsdl2cpp generates the following class for the NonEmptyArrayOfPropertyValuesType:

    class T__NonEmptyArrayOfPropertyValuesType
    {
    public:
        void setValue( const QString& arg_value );
        QString value() const;
        bool hasValueForValue() const;
        KDSoapValue serialize( const QString& valueName ) const;
        void deserialize( const KDSoapValue& mainValue );
        T__NonEmptyArrayOfPropertyValuesType();
        ~T__NonEmptyArrayOfPropertyValuesType();

    public:
        T__NonEmptyArrayOfPropertyValuesType( const T__NonEmptyArrayOfPropertyValuesType& );
        T__NonEmptyArrayOfPropertyValuesType &operator=( const T__NonEmptyArrayOfPropertyValuesType& );

    private:
        class PrivateDPtr;
        QSharedDataPointer<PrivateDPtr> d_ptr;
    };

This class only allows one value. When deserializing this only the last of the values from the element is stored.

If the maxOccurs attribute is moved from the xs:element to xs:choice the generated code is correct and works as expected (note that the value is now a QStringList, not a QString):

    class T__NonEmptyArrayOfPropertyValuesType
    {
    public:
        void setValue( const QStringList& arg_value );
        QStringList value() const;
        bool hasValueForValue() const;
        KDSoapValue serialize( const QString& valueName ) const;
        void deserialize( const KDSoapValue& mainValue );
        T__NonEmptyArrayOfPropertyValuesType();
        ~T__NonEmptyArrayOfPropertyValuesType();

    public:
        T__NonEmptyArrayOfPropertyValuesType( const T__NonEmptyArrayOfPropertyValuesType& );
        T__NonEmptyArrayOfPropertyValuesType &operator=( const T__NonEmptyArrayOfPropertyValuesType& );

    private:
        class PrivateDPtr;
        QSharedDataPointer<PrivateDPtr> d_ptr;
    };

I have tested this both on latest release and latest master (31b8e24) - with the same results.

wsdl.tar.gz

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions