SourceForge Logo
XMLRPC-EPI
A standalone C API for XML-RPC

About xmlrpc-epi
  Summary
  Features
  Projects
  History
  License

About xmlrpc-epi-php
  Summary
  Examples
  API

Documentation
  Architecture
  XMLRPC C API Reference
  Complete C API Reference
  Examples / Tutorial
  XMLRPC Protocol Spec
  RFC: system.describeMethods
  RFC: Standard Fault Codes

SourceForge
  Project Page
  Downloads
  Mailing List
  Forums
  Bug Reports
  Feature Requests
  CVS Access

XML-RPC Community
  xmlrpc.org
  xmlrpc mailing List
  online services

Related Links
  xmlrpc.org
  xmlrpc mailing List
  original expat
  new expat project
  epinions.com
  xmlrpc-c
  xmlrpc-ensor

To better illustrate how to use the library, there are some sample programs: hello_client.c, hello_server.c, sample.c, client.c, server.c, server_compliance_test.c.

hello_client and hello_server are minimalist. They are meant to be extremely simple examples of how to use the API.

Each of the rest of them takes "--help" as an argument to describe usage. Here are some things to try:

sample

implements both client (request) and server (response) behavior. The options used tell it to print both request and response. ./sample -help Usage: sample [OPTION VALUE] -help this help message -encoding <encoding> (any standard character encoding) -escaping <markup | cdata | non-ascii | non-xml | none> (may repeat) -method <methodname> -output <request | response | both> -verbosity <pretty | none | newlines> -version <xmlrpc | simple> available methods: method_TestNormal method_TestFault method_TestStruct method_TestArray method_TestBoolean method_TestInt method_TestString method_TestDouble method_TestBase64 method_TestDateTime

-output

Next we'll display both a request and a response. This is done by setting output to 'both'. Notice that we set verbosity to none, indicating that we favor compactness over prettiness. ./sample -output both -verbosity none <?xml version='1.0' ?><methodCall><methodName>method_TestNormal</methodName><params><param><value><string>This Is A test</string></value></param><param><value><int>234</int></value></param><param><value><double>234.000000</double></value></param><param><value><dateTime.iso8601>19691231T16:00:00</dateTime.iso8601></value></param><param><value><base64>VGVzdGluZyBCYXNlNjQ= </base64></value></param></params></methodCall><?xml version='1.0' ?><methodResponse><params><param><value><array><data><value><struct><member><name>Reason</name><value><string>Whew!!!</string></value></member><member><name>Rubadubdub</name><value><string>Inmytub</string></value></member></struct></value></data></array></value></param><param><value><array><data><value><string>This Is A test</string></value><value><string>One</string></value><value><string>Two</string></value><value><string>Three and four</string></value></data></array></value></param><param><value><boolean>1</boolean></value></param><param><value><int>234</int></value></param><param><value><string>This Is A test</string></value></param><param><value><double>234.000000</double></value></param><param><value><dateTime.iso8601>19691231T16:00:00</dateTime.iso8601></value></param><param><value><base64>VGVzdGluZyBCYXNlNjQ= </base64></value></param></params></methodResponse>

-verbosity

Admittedly, that was ugly. Now we'll print just the request for a method called "method_TestArray". This example uses all of sample's available arguments. First output=request. This is self-explanatory. Second, method=method_TestArray. This is a method that is exported by the "server" in sample.c. Third, verbosity=pretty. Thus we can read the output nicely. Fourth, version=xmlrpc, so the output will be in the standard xmlrpc serialization. Fifth, escaping=cdata, so all string values will be in CDATA sections. Sixth, encoding=iso-8859-1, so the xml declaration tag will include iso-8859-1, and the client/server will convert the utf-8 encoded xml into iso-8859-1 before giving the data to the application. ./sample -output request -method method_TestArray -verbosity pretty -version xmlrpc -escaping cdata -encoding "iso-8859-1" <?xml version='1.0' encoding="iso-8859-1" ?> <methodCall> <methodName><![CDATA[method_TestArray]]></methodName> <params> <param> <value> <string><![CDATA[This Is A test]]></string> </value> </param> <param> <value> <int><![CDATA[234]]></int> </value> </param> <param> <value> <double><![CDATA[234.000000]]></double> </value> </param> <param> <value> <dateTime.iso8601><![CDATA[19691231T16:00:00]]></dateTime.iso8601> </value> </param> <param> <value> <base64><![CDATA[VGVzdGluZyBCYXNlNjQ= ]]></base64> </value> </param> </params> </methodCall>

-version

That was much prettier, but still a bit verbose because each element takes up a whole line and there are several elements per value. For the rest of the examples, we will use a more compact serialization of the xml that we call "simplerpc". This is different from xmlrpc and will not work with other xmlrpc implementations. Here, we run the same command again, this time using simplerpc. See how much more readable it is? (note: although seemingly shorter due to fewer newlines, this vocab is typically a bit larger (in bytes) than xmlrpc, because of the redundant "type=" attributes.) ./sample -output request -method method_TestArray -verbosity pretty -version simple -escaping cdata -encoding "iso-8859-1" <?xml version='1.0' encoding="iso-8859-1" ?> <simpleRPC version="0.9"> <methodCall> <methodName><![CDATA[method_TestArray]]></methodName> <vector type="struct"> <scalar type="string" id="string"><![CDATA[This Is A test]]></scalar> <scalar type="int" id="int"><![CDATA[234]]></scalar> <scalar type="double" id="double"><![CDATA[234.000000]]></scalar> <scalar type="dateTime.iso8601" id="datetime"><![CDATA[19691231T16:00:00]]></scalar> <scalar type="base64" id="base64"><![CDATA[VGVzdGluZyBCYXNlNjQ= ]]></scalar> </vector> </methodCall> </simpleRPC>

-escaping

There are basically two ways to escape xml. One way is CDATA, which attempts to preserve characters as is, but will still break a parser that is expecting another encoding type. Another is numeric entity escaping, eg: &#188; to send ¼ This way, the receiving parser will know to interpret the character as 188 in whichever character encoding it is using. Xmlrpc (and these example programs) support different ways of using these methods:
  • cdata -- embed text in a cdata block
  • markup -- escape <, &, and >
  • non-ascii -- numerically escape characters above 127
  • non-print -- numerically escape non printable characters Note that these methods may be OR'd together (via command line, specify "escaping" > 1 times).

    The client program has a hard-coded ¼ in its output. If the encoding is not specified and the character is unescaped, it will likely break the parser reading the xml. Here we use the "escaping non-ascii" flag. Note the &#188; in the output.

    ./client -escaping non-ascii -version simple <?xml version='1.0' ?> <simpleRPC version="0.9"> <methodCall> <methodName>method_TestNormal</methodName> <vector type="struct"> <scalar type="string" id="string">This Is A test</scalar> <scalar type="string" id="iso_8859_1">Encoding > 127 test. This should be the symbol for 1/4: &#188;</scalar> <scalar type="int" id="int">234</scalar> <scalar type="double" id="double">234.000000</scalar> <scalar type="dateTime.iso8601" id="datetime">19691231T16:00:00</scalar> <scalar type="base64" id="base64">VGVzdGluZyBCYXNlNjQ= </scalar> </vector> </methodCall> </simpleRPC>

    -encoding

    client.c and server.c are present to show more clearly how easy it is to create just one side of the equation. In the following example, the results of the client are piped to stdin of the server, and only the server's response is printed. It is critical that the "-encoding" parameter be used, as the client embeds a character above ascii 127 in its output. If the encoding parameter were not there, the parser would assume utf-8 as the encoding, and would generate a parser error. ./client -encoding "iso-8859-1" | ./server -version simple -encoding "iso-8859-1" <?xml version='1.0' ?> <simpleRPC version="0.9"> <methodResponse> <vector type="struct"> <vector type="array"> <vector type="struct"> <scalar type="string" id="Reason">Whew!!!</scalar> <scalar type="string" id="Rubadubdub">Inmytub</scalar> </vector> </vector> <vector type="array"> <scalar type="string">This Is A test</scalar> <scalar type="string">Encoding > 127 test. This should be the symbol for 1/4: </scalar> <scalar type="string">One</scalar> <scalar type="string">Two</scalar> <scalar type="string">Three and four</scalar> </vector> <scalar type="boolean">1</scalar> <scalar type="int">25</scalar> <scalar type="string">Hello World</scalar> <scalar type="double">25.000000</scalar> <scalar type="dateTime.iso8601">19980717T14:08:55</scalar> <scalar type="base64">VTI5dFpVSmhjMlUyTkZOMGNtbHVadz09 </scalar> </vector> </methodResponse> </simpleRPC> ...and here is the error when we run without the encoding param. ./client | ./server -version simple expat reports error code 4 description: not well-formed line: 12 column: 68 byte index: 250 total bytes: 0 data beginning 10 before byte index: for 1/4: </string> and to be complete, here is what happens when we run the server without telling it the encoding for the application to use. Notice that the line with "Encoding > 127 test" contains two characters where there should be the 1/4 symbol. This is because the xmlrpc engine simply gave raw utf-8 back to the application without attempting to decode it. ./client -encoding "iso-8859-1" | ./server -version simple <?xml version='1.0' ?> <simpleRPC version="0.9"> <methodResponse> <vector type="struct"> <vector type="array"> <vector type="struct"> <scalar type="string" id="Reason">Whew!!!</scalar> <scalar type="string" id="Rubadubdub">Inmytub</scalar> </vector> </vector> <vector type="array"> <scalar type="string">This Is A test</scalar> <scalar type="string">Encoding > 127 test. This should be the symbol for 1/4: ¼</scalar> <scalar type="string">One</scalar> <scalar type="string">Two</scalar> <scalar type="string">Three and four</scalar> </vector> <scalar type="boolean">1</scalar> <scalar type="int">25</scalar> <scalar type="string">Hello World</scalar> <scalar type="double">25.000000</scalar> <scalar type="dateTime.iso8601">19980717T14:08:55</scalar> <scalar type="base64">VTI5dFpVSmhjMlUyTkZOMGNtbHVadz09 </scalar> </vector> </methodResponse> </simpleRPC>

    If you are completely confused about encodings now, don't worry about it too much. For most english applications, just stick with iso-8859-1. If you know enough to know you need something else, you probably understood all of the above anyway.