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:
Download xmlrpc-20080602a.tgz
Using this library in your code is extremely simple and documented in the header file, minixml.h, portions of which are reported below.
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.
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:
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