Search code examples
csoapgsoap

gSOAP: How to omit optional element in response?


I have a SOAP function which is defined in gSOAP syntax as

//gsoap ns service method-documentation: get foo and bar
int ns__getFooBar( xsd__string arg1, xsd__int arg2, struct ns__getFooBarResponse &response );

The response element is defined as

 //gsoap ns schema type-documentation: getFooBarResponse::foo Foo element, if available
 //gsoap ns schema type-documentation: getFooBarResponse::bar Bar element
 struct ns__getFooBarResponse { ns__FooType foo 0; ns__BarType bar; };

The resulting type definition of ns__getFooBarResponse is this:

#ifndef SOAP_TYPE_ns__getFooBarResponse
#define SOAP_TYPE_ns__getFooBarResponse (606)
/* ns:getcResponse */
struct ns__getFooBarResponse
{
public:
    ns__FooType foo;    /* SOAP 1.2 RPC return element (when namespace qualified) */    /* optional element of type ns:FooType */
    ns__BarType bar;    /* required element of type ns:BarType */
public:
    int soap_type() const { return 606; } /* = unique id SOAP_TYPE_ns__getFooBarResponse */
};
#endif

Although foo is declared as optional, it is a normal class member of ns__getFooBarResponse (for optional members, I would have expected a pointer, I guess). So foo is always present (even if just default initialized) and thus, the answer always contains a FooType element.

How can I provide a response that only contains the required BarType element but omits the optional FooType element?

TL;DR

How can I provide a SOAP response with gSOAP that omits optional elements?

EDIT

It seems the questions was unclear in parts: I do not want to get rid of the optional field completely for my application, but I want to omit it optionally if the function call only provides info for BarType (which depends on the arguments of the function call). That is why it is defined as optional:

WSDL:

<element name="getFooBarResponse">
 <complexType>
  <sequence>
   <element name="foo" type="ns:FooType" minOccurs="0" maxOccurs="1" />
   <element name="bar" type="ns:BarType" minOccurs="1" maxOccurs="1" />
  </sequence>
 </complexType>
</element>

Solution

  • The correct solution is to make foo a pointer:

    struct ns__getFooBarResponse { ns__FooType* foo 0; ns__BarType bar; };
    

    This results in

    struct hldc__getFooBarResponse 
    {
    public:
        ns__FooType *foo;   
        ns__BarType bar;    
    public:
        int soap_type() const { return 55; } 
    };
    

    In my code, I then need to manually instantiate a FooType element if needed:

    if( /* is foo data available for this response ?*/ ) 
        response.foo = soap_instantiate_ns__FooType( soap, -1, NULL, NULL, NULL );
        // fill foo with data
    }
    

    Response with FooType:

    <ns:getFooBarResponse>
        <ns:FooType> <!--"foo" content --> </FooType>
        <ns:BarType> <!--"bar" content --> </ns:BarType>
    </ns:getFooBarResponse>
    

    Response without FooType:

    <ns:getFooBarResponse>
        <ns:BarType> <!--"bar" content --> </ns:BarType>
    </ns:getFooBarResponse>