minixmlrpc - simple xmlrpc client and object manipulator

This library implements a small set of functions to parse, manipulate and print, in functional or XML format, expressions involving scalars, arrays, maps, and function calls.

The main purpose is to issue and manipulate XMLRPC calls and results from the command line or a shell, without requiring massive amounts of third party libraries or interpreters.

As it is now, the only external dependency is an SSL library, and supported options are:

The binary, dynamically linked, occupies 20-30Kbytes and builds also on OpenWRT. We are exploring the use of dropbear as an alternative to openssl.

Download xmlrpc-20080602a.tgz

LIBRARY USAGE

Using this library in your code is extremely simple and documented in the header file, minixml.h, portions of which are reported below.

STATUS, BUGS and TODO

The code is very recent so the parser is not complete and does not handle malformed input in an easy-to-control way. It should not crash, however it may return bogus responses on malformed expressions or xml, or filters.

In particular, there is still no explcit representation of 'fault' responses from the XMLRPC servers.

Example servers

The xmlrpc site reports a partial list of public services that are based on XMLRPC. Some of them are not running anymore, but you can use the others as test servers to try this program:

minixml.h

For detailed instructions on how to use the code, please look at minixml.h and xmlrpc.1 . Below are some relevant pieces from these files:

 Declare an object with 	struct __obj *o;

 You can fill it from a string using

	expr_parse(char *s, struct __obj **o, fmt)

 where fmt is FMT_FUNC or FMT_XML to parse text expressions or XMLRPC.
 You can also create the object programmatically using
 obj_calloc(...) -- see the .c file for more detail.

 Once the object is encoded, you can print it using

	obj_print(dynstr *dst, const struct __obj *o, fmt);

 The result is stored into the dynamic string passed as first arg.
 fmt = FMT_FUNC or FMT_XML selects the print format.

 An object is destroyed with	obj_free(o);

'dynstr' is an extensible string/byte array implemented by the 'dynstring' functions (also included, and very small). dynstrings are very simple to use, think of them as a C string that grows as needed, and you use ds_data(s) to access the actual string data.

 To manipulate objects, e.g. iterate and extract fields, use:

    obj_getlen(const struct __obj *) :
	    to know the number of elements in the object

    obj_get(const struct __obj *, uint32_t i, const char **key) :
	    to extract the i-th component (and possibly the key);

    obj_getfield(const struct __obj *, const char *key, int keylen) :
	    to extract the component with the given key;

 The auxiliary function
    obj_filter(dynstr *s, const struct __obj *o, const char *filter, fmt)

 supports a simple filtering language to extract, in textual form,
 components from nested ojects, or list of keys, and so on.

 Filters are a sequence of character, applied one after the other
 to the "current object", i.e. the result of previous filtering:

	(empty)		prints the object in functional form
	.xml()		prints the object in XML
	.func()		prints the object in functional form
	.length()	returns the number of elements in the object
			(1 for a scalar, or number of arguments or
			elements for functions, arrays and maps)
	.keys()		returns the space-separated list of keys for a map
	[]		applies the following filter to all components
			of the current object
	[k1,k2,...]	applies the following filter to the selected keys
			of the current object. Number are considered indexes.
			If a key ends with '=', then the object is printed
			replacing first-level separators with spaces.

 Filter examples:
   assume the object is	{a=[1,[2,3],4],b=20,c=f(1,2,3)}
   ''		returns		{a=[1,[2,3],4],b=20,c=f(1,2,3)}
   .length()	returns		3
   .keys()	returns		a b c
   []		returns		[1,[2,3],4] 20 f(1,2,3)
   [0,2]	returns		[1,[2,3],4] f(1,2,3)
   [0][1]	returns		[2,3]
   [a=]	returns		1 [2,3] 4