0

I'm trying to implement a ONVIF server (nvt) device using gsoap. I'm following the instructions and typemap.dat given in gsoap's website for code generation. I use "-P" and "-x" parameters for wsdl2h and "-S -i -x -w" for soapcpp2. Everything is working as expected, but there is a little quirk.

ONVIF core specification defines GetServices() action which includes an optional "Capabilities" member in its response under "Service" implementation. Since optional members are not created by wsdl2h (due to my parameters I guess), I make the following modification to my typemap file:

_tds__Service_Capabilities = $ xsd__anyType * Capabilities;

Then I'm able to assign custom/derived Capabilities objects to this member as required by ONVIF specification depending on the Service type implementation. However, final Capabilities object is always represented with the same namespace of GetServices() action which is not the desired operation. For instance here is the expected response (simplified):

<tds:Service>
    <tds:Capabilities>
        <tds:Capabilities>
        </tds:Capabilities>
    </tds:Capabilities>
</tds:Service>
<tds:Service>
    <tds:Capabilities>
        <trt:Capabilities>
        ...
        </trt:Capabilities>
    </tds:Capabilities>
</tds:Service>
<tds:Service>
    <tds:Capabilities>
        <tev:Capabilities>
            ...
        </tev:Capabilities>
    </tds:Capabilities>
</tds:Service>

whereas the actual response is:

<tds:Service>
    <tds:Capabilities>
        <tds:Capabilities>
        </tds:Capabilities>
    </tds:Capabilities>
</tds:Service>
<tds:Service>
    <tds:Capabilities>
        <tds:Capabilities>
        ...
        </tds:Capabilities>
    </tds:Capabilities>
</tds:Service>
<tds:Service>
    <tds:Capabilities>
        <tds:Capabilities>
            ...
        </tds:Capabilities>
    </tds:Capabilities>
</tds:Service>

To overcome this quirk, I apply following ugly patch to created soapC.cpp file:

@@ -42068,7 +51777,7 @@ void tev__Capabilities::soap_serialize(struct soap *soap) const

 int tev__Capabilities::soap_out(struct soap *soap, const char *tag, int id, const char *type) const
 {
-   return soap_out_tev__Capabilities(soap, "tev:Capabilities", id, this, type);
+   return soap_out_tev__Capabilities(soap, tag, id, this, type);
 }

 SOAP_FMAC3 int SOAP_FMAC4 soap_out_tev__Capabilities(struct soap *soap, const char *tag, int id, const tev__Capabilities *a, const char *type)
@@ -64741,7 +74450,7 @@ void trt__Capabilities::soap_serialize(struct soap *soap) const

 int trt__Capabilities::soap_out(struct soap *soap, const char *tag, int id, const char *type) const
 {
-   return soap_out_trt__Capabilities(soap, "trt:Capabilities", id, this, type);
+   return soap_out_trt__Capabilities(soap, tag, id, this, type);
 }

I have to apply this patch everytime I re-generate files and I have serious concerns that this may cause some compatibility problems in the future. What is the proper way of overriding namespace tags?

mpromonet
  • 11,326
  • 43
  • 62
  • 91

1 Answers1

1

It should not need modification in typemap.dat file, you should be able to do this using the gSOAP dom api.

In order to allow to assign DOM element to xsd_anyType you should add -d to the wsdl2h command :

-d use DOM to populate xs:any and xsd:anyType elements

Then the specialized capabilitites structure that is allocated with something like:

tev__Capabilities *tevcapabilities = soap_new_tev__Capabilities(soap);

can be set to the _any field of the tds::Capabilities structure like this:

tds__Service_Capabilities *capabilities = soap_new__tds__Service_Capabilities(soap);
capabilities->__any = soap_dom_element(soap, NULL, "tev:Capabilities", 
                          tevcapabilities, tevcapabilities->soap_type());
mpromonet
  • 11,326
  • 43
  • 62
  • 91