Question

I've been having trouble solving this problem for days, and wasn't able to find any useful resource on this on the internet, so I'll share my findings on this matter for future reference:

The Python 2.7 xmlrpclib client has the types defined by the XMLRPC standard built-in, plus a few common extensions. Other XMLRPC-servers, such as Apache, will however sometimes use their own types, or put extensions in special namespaces, etc.

For example, when you send an 8 byte integer with Apache (which is not covered by the XMLRPC standard), it will send the following response:

<methodResponse xmlns:ex="http://ws.apache.org/xmlrpc/namespaces/extensions">
    <params>
        <param>
            <value>
                <ex:i8>123456789</ex:i8>
            </value>
        </param>
    </params>
</methodResponse>

If you naively try to handle these types with Python you will get an empty tuple result. How can I adjust xmlrpclib to handle such cases?

Was it helpful?

Solution

Internally, xmlrpclib uses the xmlrpclib.Unmarshaller to dispatch responses. The Unmarshaller has a dispatch dictionary in which each type is assigned a function that will handle it.

Getting the question's example to work is actually quite easy, because xmlrpclib can already handle i8 and we only have to remap ex:i8 to that:

xmlrpclib.Unmarshaller.dispatch['ex:i8'] = xmlrpclib.Unmarshaller.dispatch['i8']

But for more custom types it might be necessary to write on dispatch functions. Those are designed to be defined within Unmarshaller, so a typical dispatch function looks like this:

def end_int(self, data):
    self.append(int(data))
    self._value = 0
dispatch['i8'] = end_int

_value = 0 just indicates that dispatching was successful. So if we had

<methodResponse>
    <params>
        <param>
            <value>
                <mycustom>some value</mycustom>
            </value>
        </param>
     </params>
</methodResponse>

we could define:

def mycustom_parser(unmarshaller, data):
    unmarshaller.append(data.split())
    unmarshaller._value = 0
xmlrpclib.Unmarshaller.dispatch['mycustom'] = mycustom_parser
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top