0

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>
Johannes S.
  • 4,566
  • 26
  • 41
  • Check out this yahoo blog. This link may not be exactly what you need to do, but if you refine the search on this site, perhaps you can find a post that deals with precisely what you need. Notice also that Robert E. is by far the biggest poster on that blog. – ryyker Jul 22 '14 at 20:19
  • @ryyker I guess you forgot to add the link to the blog you mentioned. – Johannes S. Jul 23 '14 at 07:46
  • Ooops, it appears I did, sorry. ***[LOOK HERE](https://www.cs.fsu.edu/~engelen/soapfaq.html)***, _search for_ ***Option wsdl2h -P removes unnecessary***. And also note what is being said about the typemap.dat file in that section. I also recommend, if you have not yet already done it, contacting gsoap author directly. – ryyker Jul 23 '14 at 16:06
  • I posted this questions to the gSOAP mailinglist. – Johannes S. Jul 28 '14 at 07:31
  • Did you look at the post I modified? (I did not see a comment) That method (editing the .h output of wsdl2h.exe) works to eliminate optional (or any other) elements from being generated into source. – ryyker Jul 28 '14 at 14:09
  • Thought I commented already on that post, but somehow there are no comments. However, modifying the .h will not allow me to access the optional fields for those calls where they are available. As I said: I do not want to get rid of or ignore those fields completely. I just want to be able to omit them on SOME calls (since they are optional). – Johannes S. Jul 28 '14 at 14:48
  • Oh, Okay, thanks. If you do hear of a tenable solution, I hope you will post it here as an answer. I am also interested in how to do that. All I have been able to do (as you can see) is to eliminate _Lines_ of source, not _arguments_ of functions. – ryyker Jul 28 '14 at 15:39
  • @ryyker See below (not sure if you got notified of the new answer) – Johannes S. Jul 30 '14 at 09:07
  • Thank you for posting. It seems that we are coming at our gsoap problems/solutions from opposite sides. The problems for which I use gsoap are to connect up to an existing web service. This service is created collaboratively between the organization I work in and our IT department. During development, if I see anything wrong, I arrange to have the WSDL or one of the .xsd files changed, _or_ I modify the .h file output from wsdl2h.exe. It appears you are editing the gsoap source code that is being generated after running soapCpp2.exe. Is that correct? – ryyker Jul 30 '14 at 14:47

2 Answers2

1

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>
Johannes S.
  • 4,566
  • 26
  • 41
0

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

I believe you can accomplish this by modifying the .h file output from wsdl2h utility

When you use the gsoap utility wsdl2h.exe, its output is a .h file.

Example:

c:\dev\gsoap\bin\win32\wsdl2h -c -o c:\dev\gsoapFiles\queries.h c:\dev\gsoapFiles\xyz.wsdl

This produces queries.h. This file will never be used in your project as a source file. Rather it is simply used as an input to the gsoap utility soapcpp2.exe.

Example:

c:\dev\gsoap\bin\win32\soapcpp2 -C -c queries.h  

However, before you use it this way, edit it to remove any unwanted elements.

I just did this a few minutes ago and removed 3/4 of the file's content. The .c file outputs were greatly simplified, having skipped the generation of many unnecessary lines of code.

For example, anything with ns8__... is not needed for my application, so I removed everything with that namespace designator. Such as:

/// "http://www.sample.com/Alternates/1.0":AlternateParts is a complexType.
struct ns8__AlternateParts
{
/// Element User of type xs:string.
    char*                                User                           1;  ///< Required element.
/// Element ComponentName of type xs:string.
    char*                                ComponentName                  1;  ///< Required element.
/// Element reference "http://www.physio-control.com/Alternates/1.0":Alternates.
    struct _ns8__Alternates*             Alternates                     1;  ///< Required element.
}; 

For structs, with some members not being needed, I deleted the unnecessary members. Such as:

Before

/// "urn:sample-org:xxAutoTest:xxAutoTest":atsQueryResponse is a complexType.
struct ns10__atsQueryResponse
{
/// Element result of type xs:string.
    char*                                result                         0;  ///< Optional element.
    struct _ns10__atsQueryResponse_atsData
    {
/// Element atsSerial of type xs:string.
    char*                                atsSerial                      0;  ///< Optional element.
/// Element atsWrPart of type xs:string.
    char*                                atsWrPart                      0;  ///< Optional element.
/// Element atsWrStatus of type xs:string.
    char*                                atsWrStatus                    0;  ///< Optional element.
/// Element atsBomNumber of type xs:string.
    char*                                atsBomNumber                   0;  ///< Optional element.
/// Element atsRemanIdNum of type xs:string.
    char*                                atsRemanIdNum                  0;  ///< Optional element.
/// Element atsExpiryDate of type xs:string.
    char*                                atsExpiryDate                  0;  ///< Optional element.
/// Element atsStSerialUser50 of type xs:string.
    char*                                atsStSerialUser50              0;  ///< Optional element.
    }                                   *atsData                        0;  ///< Optional element.
/// Element opResult of type xs:string.
    char*                                opResult                       0;  ///< Optional element.
/// Element opDescription of type xs:string.
    char*                                opDescription                  0;  ///< Optional element.
}; 

After

/// "urn:sample-org:xxAutoTest:xxAutoTest":atsQueryResponse is a complexType.
struct ns10__atsQueryResponse
{
/// Element result of type xs:string.
    char*                                result                         0;  ///< Optional element.
    struct _ns10__atsQueryResponse_atsData
    {
/// Element atsSerial of type xs:string.
    char*                                atsSerial                      0;  ///< Optional element.

    }                                   *atsData                        0;  ///< Optional element.
/// Element opResult of type xs:string.
    char*                                opResult                       0;  ///< Optional element.
/// Element opDescription of type xs:string.
    char*                                opDescription                  0;  ///< Optional element.
}; 
ryyker
  • 22,849
  • 3
  • 43
  • 87