7

I am new to GSOAP, so might be missing something obvious here. But I really couldn't find its solution in GSOAP documentations.

I need to know, how do I silently ignore an unknown node in my xml in GSOAP without affecting other nodes.

For example: I have below class

class gsoap_ex
{
int foo;
char bar;    
}

and below XML for it:

<gsoap_ex>
<foo>foo_value</foo>
<unknown>unknown_value</unknown>
<bar>bar_value</bar> 
</gsoap_ex>

As of now, my gsoap parses the xml till it reaches the unknown node, after that it returns without further parsing it.

print_after_parsing(gsoap_ex *obj)
{
cout<<obj->foo;
cout<<obj->bar;
}

So in my above function it shows the value of foo but value of bar is not set.

How do I achieve it?

foobar
  • 2,887
  • 2
  • 30
  • 55

1 Answers1

2

You can configure gSOAP to provide a function pointer to deal with unknown elements, and have your function decide what to do with it.

The https://www.cs.fsu.edu/~engelen/soapfaq.html page discusses handling unknown data. The first part of the paragraph is about detecting unexpected data so that you can figure out what to do about the problem; it seems you've already got that covered, so I've just included the sections detailing how to change the behavior of gSOAP.

My code appears to ignore data when receiving SOAP/XML messages. How can I detect unrecognized element tags at run time and let my application fault?

...

Another way to control the dropping of unknown elements is to define the fignore callback. For example:

{ 
    struct soap soap;   
    soap_init(&soap);   
    soap.fignore = mustmatch; // overwrite default callback   
    ...
    soap_done(&soap); // reset callbacks 
} 

int mustmatch(struct soap *soap, const char *tag) { 
    return SOAP_TAG_MISMATCH; // every tag must be handled 
}

The tag parameter contains the offending tag name. You can also selectively return a fault:

int mustmatch(struct soap *soap, const char *tag) { 

    // all tags in namespace "ns" that start with "login" are optional
    if (soap_match_tag(soap, tag, "ns:login*"))   
        return SOAP_OK;   

    // every other tag must be understood (handled)
    return SOAP_TAG_MISMATCH;
}

Presumably, you'd want to write such a callback that returns SOAP_OK for your unexpected data.

antiduh
  • 11,853
  • 4
  • 43
  • 66
  • I tried what you suggested but somehow it doesn't work for me. My `mustmatch` function which I assigned to `soap->fignore` never gets hit, so the default behavior continues. – foobar Apr 11 '15 at 06:55
  • @foobar - Have you tied setting `soap_set_imode(&soap, SOAP_XML_STRICT)`? – antiduh Apr 11 '15 at 20:13
  • Below are my settings: `m_soap.namespaces = namespaces; soap_init2(&m_soap, SOAP_XML_TREE, SOAP_XML_TREE | SOAP_XML_IGNORENS); m_soap.fignore = must_match; soap_set_imode(&m_soap, SOAP_XML_TREE | SOAP_XML_IGNORENS); soap_imode(&m_soap, SOAP_XML_TREE);` – foobar Apr 13 '15 at 05:38
  • @foobar - I don't see SOAP_XML_STRICT in there, the faq I linked seems to indicate that is what you need in order to use `fignore`. – antiduh Apr 13 '15 at 15:26
  • it doesnt work even after doing `soap_set_imode(&soap,SOAP_XML_STRICT)` is there anyother setting I need to do? – foobar Apr 14 '15 at 10:19
  • Do your gsoap header files define `//gsoap` namespace declarations? Why do you have IGNORENS turned on? Why do you assign to `m_soap.namespace` before calling `soap_init`? Why do you set each `imode` and `omode` multiple times (the `soap_init2` call should be enough)? It seems that with proper namespace declarations and processing, this should do something - either work, call your `fignore` handler, or throw an exception. Reading between the lines of the FAQ, I get the impression that improper or incomplete namespace handling could be part of the problem. – antiduh Apr 14 '15 at 14:45