Ignore an unknown XML element node in GSOAP
Asked Answered
M

1

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?

Mert answered 8/4, 2015 at 11:10 Comment(0)
A
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.

Angeliaangelic answered 10/4, 2015 at 15:13 Comment(6)
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.Mert
@Mert - Have you tied setting soap_set_imode(&soap, SOAP_XML_STRICT)?Angeliaangelic
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);Mert
@Mert - 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.Angeliaangelic
it doesnt work even after doing soap_set_imode(&soap,SOAP_XML_STRICT) is there anyother setting I need to do?Mert
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.Angeliaangelic

© 2022 - 2024 — McMap. All rights reserved.