1074 lines
57 KiB
Plaintext
1074 lines
57 KiB
Plaintext
|
XML-RPC HOWTO
|
|||
|
|
|||
|
Eric Kidd
|
|||
|
|
|||
|
Source Builders
|
|||
|
|
|||
|
eric.kidd@pobox.com
|
|||
|
|
|||
|
And Other Contributors
|
|||
|
|
|||
|
Copyright <20> 2001 by Eric Kidd
|
|||
|
|
|||
|
0.8.0, 2001-04-12
|
|||
|
Revision History
|
|||
|
Revision 0.8.0 2001-04-12
|
|||
|
Updated section on common interfaces. Added pointer to XML-RPC.Net
|
|||
|
information.
|
|||
|
Revision 0.7.0 2001-04-03
|
|||
|
Added section on C++ proxy classes.
|
|||
|
Revision 0.6.0 2001-02-02
|
|||
|
Added sections on Ruby, K and common interfaces.
|
|||
|
Revision 0.5.0 2001-01-23
|
|||
|
Initial version.
|
|||
|
|
|||
|
|
|||
|
Describes how to use XML-RPC to implement clients and servers in a variety of
|
|||
|
languages. Provides example code in Perl, Python, C, C++, Java, PHP and other
|
|||
|
languages. Includes sections on Zope and KDE 2.0. Applies to all operating
|
|||
|
systems with XML-RPC support.
|
|||
|
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
Table of Contents
|
|||
|
1. Legal Notice
|
|||
|
2. What is XML-RPC?
|
|||
|
2.1. How it Works
|
|||
|
2.2. Supported Data Types
|
|||
|
2.3. The History of XML-RPC
|
|||
|
|
|||
|
|
|||
|
3. XML-RPC vs. Other Protocols
|
|||
|
3.1. XML-RPC vs. CORBA
|
|||
|
3.2. XML-RPC vs. DCOM
|
|||
|
3.3. XML-RPC vs. SOAP
|
|||
|
|
|||
|
|
|||
|
4. Common XML-RPC Interfaces
|
|||
|
4.1. Introspection: Discovering Server APIs
|
|||
|
4.2. Boxcarring: Sending Multiple Requests at Once
|
|||
|
|
|||
|
|
|||
|
5. A Sample API: sumAndDifference
|
|||
|
6. Using XML-RPC with Perl
|
|||
|
6.1. A Perl Client
|
|||
|
6.2. A Stand-Alone Perl Server
|
|||
|
6.3. A CGI-Based Perl Server
|
|||
|
|
|||
|
|
|||
|
7. Using XML-RPC with Python
|
|||
|
7.1. A Python Client
|
|||
|
|
|||
|
|
|||
|
8. Using XML-RPC with C and C++
|
|||
|
8.1. A C Client
|
|||
|
8.2. A C++ Client
|
|||
|
8.3. A C++ Client with Proxy Classes
|
|||
|
8.4. A CGI-Based C Server
|
|||
|
|
|||
|
|
|||
|
9. Using XML-RPC with Java
|
|||
|
9.1. A Java Client
|
|||
|
9.2. A Stand-Alone Java Server
|
|||
|
|
|||
|
|
|||
|
10. Using XML-RPC with PHP
|
|||
|
10.1. A PHP Client
|
|||
|
10.2. A PHP Server
|
|||
|
|
|||
|
|
|||
|
11. Using XML-RPC with Microsoft .NET
|
|||
|
12. Using XML-RPC with Ruby
|
|||
|
12.1. A Ruby Client
|
|||
|
12.2. A Ruby Server
|
|||
|
|
|||
|
|
|||
|
13. Using XML-RPC with Proprietary Languages
|
|||
|
13.1. Using XML-RPC with K
|
|||
|
|
|||
|
|
|||
|
14. Applications with Built-in XML-RPC Support
|
|||
|
14.1. Zope
|
|||
|
14.2. KDE 2.0
|
|||
|
|
|||
|
|
|||
|
15. About This Document
|
|||
|
15.1. New Versions of This Document
|
|||
|
15.2. Contributors to the XML-RPC HOWTO
|
|||
|
15.3. Submitting Other Snippets
|
|||
|
|
|||
|
|
|||
|
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
1. Legal Notice
|
|||
|
|
|||
|
Permission is granted to copy, distribute and/or modify this document under
|
|||
|
the terms of the GNU Free Documentation License, Version 1.1 or any later
|
|||
|
version published by the Free Software Foundation with no Invariant Sections,
|
|||
|
no Front-Cover Texts, and no Back-Cover Texts. You may obtain a copy of the
|
|||
|
GNU Free Documentation License from the Free Software Foundation by visiting
|
|||
|
[http://www.fsf.org/] their Web site or by writing to: Free Software
|
|||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
|
|||
|
This manual contains short example programs ("the Software"). Permission is
|
|||
|
hereby granted, free of charge, to any person obtaining a copy of the
|
|||
|
Software, to deal in the Software without restriction, including without
|
|||
|
limitation the rights to use, copy, modify, merge, publish, distribute,
|
|||
|
sublicense, and/or sell copies of the Software, and to permit persons to whom
|
|||
|
the Software is furnished to do so, subject to the following condition:
|
|||
|
|
|||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|||
|
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|||
|
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
2. What is XML-RPC?
|
|||
|
|
|||
|
[http://www.xmlrpc.com/] XML-RPC is a simple, portable way to make remote
|
|||
|
procedure calls over HTTP. It can be used with Perl, Java, Python, C, C++,
|
|||
|
PHP and many other programming languages. Implementations are available for
|
|||
|
Unix, Windows and the Macintosh.
|
|||
|
|
|||
|
Here's a short XML-RPC client written in Perl. (We use Ken MacLeod's [http://
|
|||
|
bitsko.slc.ut.us/~ken/xml-rpc/] Frontier::Client module.)
|
|||
|
use Frontier::Client;
|
|||
|
$server = Frontier::Client->new(url => 'http://betty.userland.com/RPC2');
|
|||
|
$name = $server->call('examples.getStateName', 41);
|
|||
|
print "$name\n";
|
|||
|
|
|||
|
When run, this program will connect to the remote server, get the state name,
|
|||
|
and print it. (State #41 should be South Dakota in this example.)
|
|||
|
|
|||
|
Here's the same program in Python. (This time, we use Fredrik Lundh's [http:/
|
|||
|
/www.pythonware.com/products/xmlrpc/] xmlrpclib.)
|
|||
|
python> import xmlrpclib
|
|||
|
python> server = xmlrpclib.Server("http://betty.userland.com/RPC2")
|
|||
|
python> server.examples.getStateName(41)
|
|||
|
'South Dakota'
|
|||
|
|
|||
|
In the following chapters, you'll learn how to write XML-RPC clients and
|
|||
|
servers in a variety of programming languages.
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
2.1. How it Works
|
|||
|
|
|||
|
XML-RPC is described fully in Dave Winer's [http://www.xmlrpc.com/spec]
|
|||
|
official specification. If you're curious, go ahead and take a look??it's a
|
|||
|
quick and straight-forward read.
|
|||
|
|
|||
|
On the wire, XML-RPC values are encoded as XML:
|
|||
|
<methodCall>
|
|||
|
<methodName>sample.sumAndDifference</methodName>
|
|||
|
<params>
|
|||
|
<param><value><int>5</int></value></param>
|
|||
|
<param><value><int>3</int></value></param>
|
|||
|
</params>
|
|||
|
</methodCall>
|
|||
|
|
|||
|
This is verbose, but compresses readily. It's also faster than you might
|
|||
|
expect??according to measurements by Rick Blair, a round-trip XML-RPC call
|
|||
|
takes 3 milliseconds using Hannes Walln<6C>fer's Java implementation.
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
2.2. Supported Data Types
|
|||
|
|
|||
|
XML-RPC supports the following data types:
|
|||
|
|
|||
|
int
|
|||
|
A signed, 32-bit integer.
|
|||
|
|
|||
|
string
|
|||
|
An ASCII string, which may contain NULL bytes. (Actually, several XML-RPC
|
|||
|
implementations support Unicode, thanks to the underlying features of
|
|||
|
XML.)
|
|||
|
|
|||
|
boolean
|
|||
|
Either true or false.
|
|||
|
|
|||
|
double
|
|||
|
A double-precision floating point number. (Accuracy may be limited in
|
|||
|
some implementations.)
|
|||
|
|
|||
|
dateTime.iso8601
|
|||
|
A date and time. Unfortunately, since XML-RPC forbids the use of
|
|||
|
timezones, this is very nearly useless.
|
|||
|
|
|||
|
base64
|
|||
|
Raw binary data of any length; encoded using Base64 on the wire. Very
|
|||
|
useful. (Some implementations don't like to receive zero bytes of data,
|
|||
|
though.)
|
|||
|
|
|||
|
array
|
|||
|
An one-dimensional array of values. Individual values may be of any type.
|
|||
|
|
|||
|
struct
|
|||
|
A collection of key-value pairs. The keys are strings; the values may be
|
|||
|
of any type.
|
|||
|
|
|||
|
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
2.3. The History of XML-RPC
|
|||
|
|
|||
|
XML-RPC was inspired by two earlier protocols. The first is an anonymous RPC
|
|||
|
protocol designed by Dave Winer and announced in an old DaveNet essay. (This
|
|||
|
is why XML-RPC servers are often installed under /RPC2.) The other, more
|
|||
|
important inspiration was an early draft of the SOAP protocol.
|
|||
|
|
|||
|
A longer history of XML-RPC has been generously provided by Dave Winer. This
|
|||
|
also explains the relationship between XML-RPC and SOAP.
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
3. XML-RPC vs. Other Protocols
|
|||
|
|
|||
|
XML-RPC is not the only way to make remote procedure calls. Other popular
|
|||
|
protocols include CORBA, DCOM and SOAP. Each of these protocols has
|
|||
|
advantages and disadvantages.
|
|||
|
|
|||
|
The opinions in the section are obviously biased; please take them with a
|
|||
|
grain of salt.
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
3.1. XML-RPC vs. CORBA
|
|||
|
|
|||
|
[http://www.corba.org/] CORBA is a popular protocol for writing distributed,
|
|||
|
object-oriented applications. It's typically used in multi-tier enterprise
|
|||
|
applications. Recently, it's also been adopted by the [http://www.gnome.org/]
|
|||
|
Gnome project for interapplication communication.
|
|||
|
|
|||
|
CORBA is well-supported by many vendors and several free software projects.
|
|||
|
CORBA works well with Java and C++, and is available for many other
|
|||
|
languages. CORBA also provides an excellent interface definition language
|
|||
|
(IDL), allowing you to define readable, object-oriented APIs.
|
|||
|
|
|||
|
Unfortunately, CORBA is very complex. It has a steep learning curve, requires
|
|||
|
significant effort to implement, and requires fairly sophisticated clients.
|
|||
|
It's better-suited to enterprise and desktop applications than it is to
|
|||
|
distributed web applications.
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
3.2. XML-RPC vs. DCOM
|
|||
|
|
|||
|
[http://www.microsoft.com/com/tech/DCOM.asp] DCOM is Microsoft's answer to
|
|||
|
CORBA. It's great if you're already using COM components, and you don't need
|
|||
|
to talk to non-Microsoft systems. Otherwise, it won't help you very much.
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
3.3. XML-RPC vs. SOAP
|
|||
|
|
|||
|
[http://www.w3.org/TR/SOAP/] SOAP is very similar to XML-RPC. It, too, works
|
|||
|
by marshaling procedure calls over HTTP as XML documents. Unfortunately, SOAP
|
|||
|
appears to be suffering from specification creep.
|
|||
|
|
|||
|
SOAP was originally created as a collaboration between UserLand,
|
|||
|
DevelopMentor and Microsoft. The initial public release was basically XML-RPC
|
|||
|
with namespaces and longer element names. Since then, however, SOAP has been
|
|||
|
turned over a W3C working group.
|
|||
|
|
|||
|
Unfortunately, the working group has been adding a laundry-list of strange
|
|||
|
features to SOAP. As of the current writing, SOAP supports XML Schemas,
|
|||
|
enumerations, strange hybrids of structs and arrays, and custom types. At the
|
|||
|
same time, several aspects of SOAP are implementation defined.
|
|||
|
|
|||
|
Basically, if you like XML-RPC, but wish the protocol had more features,
|
|||
|
check out SOAP. :-)
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
4. Common XML-RPC Interfaces
|
|||
|
|
|||
|
Several XML-RPC servers provide built-in methods. These aren't part of
|
|||
|
XML-RPC itself, but they make handy add-ons.
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
4.1. Introspection: Discovering Server APIs
|
|||
|
|
|||
|
Edd Dumbill [http://xmlrpc.usefulinc.com/doc/reserved.html] proposed the
|
|||
|
following set of methods:
|
|||
|
array system.listMethods ()
|
|||
|
string system.methodHelp (string methodName)
|
|||
|
array system.methodSignature (string methodName)
|
|||
|
|
|||
|
If a server supports these methods, you can ask it to print out some
|
|||
|
documentation:
|
|||
|
import xmlrpclib
|
|||
|
server = xmlrpclib.Server("http://xmlrpc-c.sourceforge.net/api/sample.php")
|
|||
|
for method in server.system.listMethods():
|
|||
|
print method
|
|||
|
print server.system.methodHelp(method)
|
|||
|
print
|
|||
|
|
|||
|
These methods are currently supported by servers written in PHP, C and
|
|||
|
Microsoft .NET. Partial introspection support is included in recent updates
|
|||
|
to UserLand Frontier. Introspection support for Perl, Python and Java is
|
|||
|
available at the XML-RPC Hacks page. Please feel free to add introspection
|
|||
|
support to other XML-RPC servers!
|
|||
|
|
|||
|
Various client-side tools (documentation generators, wrapper generators, and
|
|||
|
so on) can be found at the XML-RPC Hacks page as well.
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
4.2. Boxcarring: Sending Multiple Requests at Once
|
|||
|
|
|||
|
If you're writing an XML-RPC client which makes lots of small function calls,
|
|||
|
you may discover that your round-trip time is fairly high, thanks to Internet
|
|||
|
backbone latency. Some servers allow you to batch up multiple requests using
|
|||
|
the following function:
|
|||
|
array system.multicall (array calls)
|
|||
|
|
|||
|
You can find more information in the system.multicall RFC.
|
|||
|
|
|||
|
This method is currently supported by servers written in C and UserLand
|
|||
|
Frontier. Servers written in Python and Perl can use the code at the XML-RPC
|
|||
|
Hacks page.
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
5. A Sample API: sumAndDifference
|
|||
|
|
|||
|
To demonstrate XML-RPC, we implement the following API in as many languages
|
|||
|
as possible.
|
|||
|
struct sample.sumAndDifference (int x, int y)
|
|||
|
|
|||
|
This function takes two integers as arguments, and returns an XML-RPC <struct
|
|||
|
> containing two elements:
|
|||
|
|
|||
|
sum
|
|||
|
The sum of the two integers.
|
|||
|
|
|||
|
difference
|
|||
|
The difference between the two integers.
|
|||
|
|
|||
|
|
|||
|
It's not very useful, but it makes a nice example. :-)
|
|||
|
|
|||
|
This function (and others) are available using the URL http://
|
|||
|
xmlrpc-c.sourceforge.net/api/sample.php. (This URL won't do anything in a
|
|||
|
browser; it requires an XML-RPC client.)
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
6. Using XML-RPC with Perl
|
|||
|
|
|||
|
Ken MacLeod has implemented XML-RPC for Perl. You can find his Frontier::RPC
|
|||
|
module at his [http://bitsko.slc.ut.us/~ken/xml-rpc/] website or through
|
|||
|
[http://www.cpan.org/] CPAN.
|
|||
|
|
|||
|
To install Frontier::RPC, download the package and compile it in the standard
|
|||
|
fashion:
|
|||
|
bash$ gunzip -c Frontier-RPC-0.07b1.tar.gz | tar xvf -
|
|||
|
bash$ cd Frontier-RPC-0.07b1
|
|||
|
bash$ perl Makefile.PL
|
|||
|
bash$ make
|
|||
|
bash$ make test
|
|||
|
bash$ su -c 'make install'
|
|||
|
|
|||
|
(The process will be slightly different on Windows systems, or if you don't
|
|||
|
have root access. Consult your Perl documentation for details.)
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
6.1. A Perl Client
|
|||
|
|
|||
|
The following program shows how to call an XML-RPC server from Perl:
|
|||
|
use Frontier::Client;
|
|||
|
|
|||
|
# Make an object to represent the XML-RPC server.
|
|||
|
$server_url = 'http://xmlrpc-c.sourceforge.net/api/sample.php';
|
|||
|
$server = Frontier::Client->new(url => $server_url);
|
|||
|
|
|||
|
# Call the remote server and get our result.
|
|||
|
$result = $server->call('sample.sumAndDifference', 5, 3);
|
|||
|
$sum = $result->{'sum'};
|
|||
|
$difference = $result->{'difference'};
|
|||
|
|
|||
|
print "Sum: $sum, Difference: $difference\n";
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
6.2. A Stand-Alone Perl Server
|
|||
|
|
|||
|
The following program shows how to write an XML-RPC server in Perl:
|
|||
|
use Frontier::Daemon;
|
|||
|
|
|||
|
sub sumAndDifference {
|
|||
|
my ($x, $y) = @_;
|
|||
|
return {'sum' => $x + $y, 'difference' => $x - $y};
|
|||
|
}
|
|||
|
|
|||
|
# Call me as http://localhost:8080/RPC2
|
|||
|
$methods = {'sample.sumAndDifference' => \&sumAndDifference};
|
|||
|
Frontier::Daemon->new(LocalPort => 8080, methods => $methods)
|
|||
|
or die "Couldn't start HTTP server: $!";
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
6.3. A CGI-Based Perl Server
|
|||
|
|
|||
|
Frontier::RPC2 doesn't provide built-in support for CGI-based servers. It
|
|||
|
does, however, provide most of the pieces you'll need.
|
|||
|
|
|||
|
Save the following code as sumAndDifference.cgi in your web server's cgi-bin
|
|||
|
directory. (On Unix systems, you'll need to make it executable by typing
|
|||
|
chmod +x sumAndDifference.cgi.)
|
|||
|
#!/usr/bin/perl -w
|
|||
|
|
|||
|
use strict;
|
|||
|
use Frontier::RPC2;
|
|||
|
|
|||
|
sub sumAndDifference {
|
|||
|
my ($x, $y) = @_;
|
|||
|
return {'sum' => $x + $y, 'difference' => $x - $y};
|
|||
|
}
|
|||
|
|
|||
|
process_cgi_call({'sample.sumAndDifference' => \&sumAndDifference});
|
|||
|
|
|||
|
|
|||
|
#==========================================================================
|
|||
|
# CGI Support
|
|||
|
#==========================================================================
|
|||
|
# Simple CGI support for Frontier::RPC2. You can copy this into your CGI
|
|||
|
# scripts verbatim, or you can package it into a library.
|
|||
|
# (Based on xmlrpc_cgi.c by Eric Kidd <http://xmlrpc-c.sourceforge.net/>.)
|
|||
|
|
|||
|
# Process a CGI call.
|
|||
|
sub process_cgi_call ($) {
|
|||
|
my ($methods) = @_;
|
|||
|
|
|||
|
# Get our CGI request information.
|
|||
|
my $method = $ENV{'REQUEST_METHOD'};
|
|||
|
my $type = $ENV{'CONTENT_TYPE'};
|
|||
|
my $length = $ENV{'CONTENT_LENGTH'};
|
|||
|
|
|||
|
# Perform some sanity checks.
|
|||
|
http_error(405, "Method Not Allowed") unless $method eq "POST";
|
|||
|
http_error(400, "Bad Request") unless $type eq "text/xml";
|
|||
|
http_error(411, "Length Required") unless $length > 0;
|
|||
|
|
|||
|
# Fetch our body.
|
|||
|
my $body;
|
|||
|
my $count = read STDIN, $body, $length;
|
|||
|
http_error(400, "Bad Request") unless $count == $length;
|
|||
|
|
|||
|
# Serve our request.
|
|||
|
my $coder = Frontier::RPC2->new;
|
|||
|
send_xml($coder->serve($body, $methods));
|
|||
|
}
|
|||
|
|
|||
|
# Send an HTTP error and exit.
|
|||
|
sub http_error ($$) {
|
|||
|
my ($code, $message) = @_;
|
|||
|
print <<"EOD";
|
|||
|
Status: $code $message
|
|||
|
Content-type: text/html
|
|||
|
|
|||
|
<title>$code $message</title>
|
|||
|
<h1>$code $message</h1>
|
|||
|
<p>Unexpected error processing XML-RPC request.</p>
|
|||
|
EOD
|
|||
|
exit 0;
|
|||
|
}
|
|||
|
|
|||
|
# Send an XML document (but don't exit).
|
|||
|
sub send_xml ($) {
|
|||
|
my ($xml_string) = @_;
|
|||
|
my $length = length($xml_string);
|
|||
|
print <<"EOD";
|
|||
|
Status: 200 OK
|
|||
|
Content-type: text/xml
|
|||
|
Content-length: $length
|
|||
|
|
|||
|
EOD
|
|||
|
# We want precise control over whitespace here.
|
|||
|
print $xml_string;
|
|||
|
}
|
|||
|
|
|||
|
You can copy the utility routines into your own CGI scripts.
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
7. Using XML-RPC with Python
|
|||
|
|
|||
|
Fredrik Lundh has provided an excellent XML-RPC library for Python.
|
|||
|
|
|||
|
To install, download the latest version. You can either stick the *.py files
|
|||
|
in the same directory as your Python code, or you can install them in your
|
|||
|
system's Python directory.
|
|||
|
|
|||
|
RedHat 6.2 users can type the following:
|
|||
|
bash$ mkdir xmlrpclib-0.9.8
|
|||
|
bash$ cd xmlrpclib-0.9.8
|
|||
|
bash$ unzip ../xmlrpc-0.9.8-990621.zip
|
|||
|
bash$ python
|
|||
|
python> import xmlrpclib
|
|||
|
python> import xmlrpcserver
|
|||
|
python> Control-D
|
|||
|
bash$ su -c 'cp *.py *.pyc /usr/lib/python1.5/'
|
|||
|
|
|||
|
We import two of the *.py files to trick Python into compiling them. Users of
|
|||
|
other platforms should consult their Python documentation.
|
|||
|
|
|||
|
For more Python examples, see the article XML-RPC: It Works Both Ways on the
|
|||
|
O'Reilly Network.
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
7.1. A Python Client
|
|||
|
|
|||
|
The following program shows how to call an XML-RPC server from Python:
|
|||
|
import xmlrpclib
|
|||
|
|
|||
|
# Create an object to represent our server.
|
|||
|
server_url = 'http://xmlrpc-c.sourceforge.net/api/sample.php';
|
|||
|
server = xmlrpclib.Server(server_url);
|
|||
|
|
|||
|
# Call the server and get our result.
|
|||
|
result = server.sample.sumAndDifference(5, 3)
|
|||
|
print "Sum:", result['sum']
|
|||
|
print "Difference:", result['difference']
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
8. Using XML-RPC with C and C++
|
|||
|
|
|||
|
To get a copy of XML-RPC for C/C++, see the [http://xmlrpc-c.sourceforge.net]
|
|||
|
xmlrpc-c website.
|
|||
|
|
|||
|
You can either download everything in RPM format, or you can build it from
|
|||
|
source.
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
8.1. A C Client
|
|||
|
|
|||
|
Save the following code in a file called getSumAndDifference.c:
|
|||
|
#include <stdio.h>
|
|||
|
#include <xmlrpc.h>
|
|||
|
#include <xmlrpc_client.h>
|
|||
|
|
|||
|
#define NAME "XML-RPC getSumAndDifference C Client"
|
|||
|
#define VERSION "0.1"
|
|||
|
#define SERVER_URL "http://xmlrpc-c.sourceforge.net/api/sample.php"
|
|||
|
|
|||
|
void die_if_fault_occurred (xmlrpc_env *env)
|
|||
|
{
|
|||
|
/* Check our error-handling environment for an XML-RPC fault. */
|
|||
|
if (env->fault_occurred) {
|
|||
|
fprintf(stderr, "XML-RPC Fault: %s (%d)\n",
|
|||
|
env->fault_string, env->fault_code);
|
|||
|
exit(1);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
int main (int argc, char** argv)
|
|||
|
{
|
|||
|
xmlrpc_env env;
|
|||
|
xmlrpc_value *result;
|
|||
|
xmlrpc_int32 sum, difference;
|
|||
|
|
|||
|
/* Start up our XML-RPC client library. */
|
|||
|
xmlrpc_client_init(XMLRPC_CLIENT_NO_FLAGS, NAME, VERSION);
|
|||
|
xmlrpc_env_init(&env);
|
|||
|
|
|||
|
/* Call our XML-RPC server. */
|
|||
|
result = xmlrpc_client_call(&env, SERVER_URL,
|
|||
|
"sample.sumAndDifference", "(ii)",
|
|||
|
(xmlrpc_int32) 5,
|
|||
|
(xmlrpc_int32) 3);
|
|||
|
die_if_fault_occurred(&env);
|
|||
|
|
|||
|
/* Parse our result value. */
|
|||
|
xmlrpc_parse_value(&env, result, "{s:i,s:i,*}",
|
|||
|
"sum", &sum,
|
|||
|
"difference", &difference);
|
|||
|
die_if_fault_occurred(&env);
|
|||
|
|
|||
|
/* Print out our sum and difference. */
|
|||
|
printf("Sum: %d, Difference: %d\n", (int) sum, (int) difference);
|
|||
|
|
|||
|
/* Dispose of our result value. */
|
|||
|
xmlrpc_DECREF(result);
|
|||
|
|
|||
|
/* Shutdown our XML-RPC client library. */
|
|||
|
xmlrpc_env_clean(&env);
|
|||
|
xmlrpc_client_cleanup();
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
To compile it, you can type:
|
|||
|
bash$ CLIENT_CFLAGS=`xmlrpc-c-config libwww-client --cflags`
|
|||
|
bash$ CLIENT_LIBS=`xmlrpc-c-config libwww-client --libs`
|
|||
|
bash$ gcc $CLIENT_CFLAGS -o getSumAndDifference getSumAndDifference.c $CLIENT_LIBS
|
|||
|
|
|||
|
You may need to replace gcc with the name of your system's C compiler.
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
8.2. A C++ Client
|
|||
|
|
|||
|
Save the following code in a file called getSumAndDifference2.cc:
|
|||
|
#include <iostream.h>
|
|||
|
#include <XmlRpcCpp.h>
|
|||
|
|
|||
|
#define NAME "XML-RPC getSumAndDifference C++ Client"
|
|||
|
#define VERSION "0.1"
|
|||
|
#define SERVER_URL "http://xmlrpc-c.sourceforge.net/api/sample.php"
|
|||
|
|
|||
|
static void get_sum_and_difference () {
|
|||
|
|
|||
|
// Build our parameter array.
|
|||
|
XmlRpcValue param_array = XmlRpcValue::makeArray();
|
|||
|
param_array.arrayAppendItem(XmlRpcValue::makeInt(5));
|
|||
|
param_array.arrayAppendItem(XmlRpcValue::makeInt(3));
|
|||
|
|
|||
|
// Create an object to resprent the server, and make our call.
|
|||
|
XmlRpcClient server (SERVER_URL);
|
|||
|
XmlRpcValue result = server.call("sample.sumAndDifference", param_array);
|
|||
|
|
|||
|
// Extract the sum and difference from our struct.
|
|||
|
XmlRpcValue::int32 sum = result.structGetValue("sum").getInt();
|
|||
|
XmlRpcValue::int32 diff = result.structGetValue("difference").getInt();
|
|||
|
|
|||
|
cout << "Sum: " << sum << ", Difference: " << diff << endl;
|
|||
|
}
|
|||
|
|
|||
|
int main (int argc, char **argv) {
|
|||
|
|
|||
|
// Start up our client library.
|
|||
|
XmlRpcClient::Initialize(NAME, VERSION);
|
|||
|
|
|||
|
// Call our client routine, and watch out for faults.
|
|||
|
try {
|
|||
|
get_sum_and_difference();
|
|||
|
} catch (XmlRpcFault& fault) {
|
|||
|
cerr << argv[0] << ": XML-RPC fault #" << fault.getFaultCode()
|
|||
|
<< ": " << fault.getFaultString() << endl;
|
|||
|
XmlRpcClient::Terminate();
|
|||
|
exit(1);
|
|||
|
}
|
|||
|
|
|||
|
// Shut down our client library.
|
|||
|
XmlRpcClient::Terminate();
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
To compile it, you can type:
|
|||
|
bash$ CLIENT_CFLAGS=`xmlrpc-c-config c++ libwww-client --cflags`
|
|||
|
bash$ CLIENT_LIBS=`xmlrpc-c-config c++ libwww-client --libs`
|
|||
|
bash$ c++ $CLIENT_CFLAGS -o getSumAndDifference2 getSumAndDifference2.cc $CLIENT_LIBS
|
|||
|
|
|||
|
You'll need a reasonably modern C++ compiler for this to work.
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
8.3. A C++ Client with Proxy Classes
|
|||
|
|
|||
|
If your XML-RPC server supports the Introspection API, you can automatically
|
|||
|
generate C++ proxy classes for it. To generate a proxy class, type the
|
|||
|
following command and save the output to a file:
|
|||
|
bash$ xml-rpc-api2cpp \
|
|||
|
> http://xmlrpc-c.sourceforge.net/api/sample.php sample SampleProxy
|
|||
|
|
|||
|
This will generate a proxy class named SampleProxy containing wrappers for
|
|||
|
all the methods beginning with sample. You can edit this class in any fashion
|
|||
|
you'd like.
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
8.4. A CGI-Based C Server
|
|||
|
|
|||
|
Save the following code in a file called sumAndDifference.c:
|
|||
|
#include <xmlrpc.h>
|
|||
|
#include <xmlrpc_cgi.h>
|
|||
|
|
|||
|
xmlrpc_value *
|
|||
|
sumAndDifference (xmlrpc_env *env, xmlrpc_value *param_array, void *user_data)
|
|||
|
{
|
|||
|
xmlrpc_int32 x, y;
|
|||
|
|
|||
|
/* Parse our argument array. */
|
|||
|
xmlrpc_parse_value(env, param_array, "(ii)", &x, &y);
|
|||
|
if (env->fault_occurred)
|
|||
|
return NULL;
|
|||
|
|
|||
|
/* Return our result. */
|
|||
|
return xmlrpc_build_value(env, "{s:i,s:i}",
|
|||
|
"sum", x + y,
|
|||
|
"difference", x - y);
|
|||
|
}
|
|||
|
|
|||
|
int main (int argc, char **argv)
|
|||
|
{
|
|||
|
/* Set up our CGI library. */
|
|||
|
xmlrpc_cgi_init(XMLRPC_CGI_NO_FLAGS);
|
|||
|
|
|||
|
/* Install our only method (with a method signature and a help string). */
|
|||
|
xmlrpc_cgi_add_method_w_doc("sample.sumAndDifference",
|
|||
|
&sumAndDifference, NULL,
|
|||
|
"S:ii", "Add and subtract two integers.");
|
|||
|
|
|||
|
/* Call the appropriate method. */
|
|||
|
xmlrpc_cgi_process_call();
|
|||
|
|
|||
|
/* Clean up our CGI library. */
|
|||
|
xmlrpc_cgi_cleanup();
|
|||
|
}
|
|||
|
|
|||
|
To compile it, you can type:
|
|||
|
bash$ CGI_CFLAGS=`xmlrpc-c-config cgi-server --cflags`
|
|||
|
bash$ CGI_LIBS=`xmlrpc-c-config cgi-server --libs`
|
|||
|
bash$ gcc $CGI_CFLAGS -o sumAndDifference.cgi sumAndDifference.c $CGI_LIBS
|
|||
|
|
|||
|
Once this is done, copy sumAndDifference.cgi into your webserver's cgi-bin
|
|||
|
directory.
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
9. Using XML-RPC with Java
|
|||
|
|
|||
|
Hannes Walln<6C>fer has provided an excellent implementation of XML-RPC for
|
|||
|
Java.
|
|||
|
|
|||
|
To install it, download the distribution, unzip it, and add the *.jar files
|
|||
|
to your CLASSPATH. On a Unix system, you can do this by typing:
|
|||
|
bash$ unzip xmlrpc-java.zip
|
|||
|
bash$ cd xmlrpc-java/lib
|
|||
|
bash$ CLASSPATH=`pwd`/openxml-1.2.jar:`pwd`/xmlrpc.jar:$CLASSPATH
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
9.1. A Java Client
|
|||
|
|
|||
|
Save the following program in a file named JavaClient.java.
|
|||
|
import java.util.Vector;
|
|||
|
import java.util.Hashtable;
|
|||
|
import helma.xmlrpc.*;
|
|||
|
|
|||
|
public class JavaClient {
|
|||
|
|
|||
|
// The location of our server.
|
|||
|
private final static String server_url =
|
|||
|
"http://xmlrpc-c.sourceforge.net/api/sample.php";
|
|||
|
|
|||
|
public static void main (String [] args) {
|
|||
|
try {
|
|||
|
|
|||
|
// Create an object to represent our server.
|
|||
|
XmlRpcClient server = new XmlRpcClient(server_url);
|
|||
|
|
|||
|
// Build our parameter list.
|
|||
|
Vector params = new Vector();
|
|||
|
params.addElement(new Integer(5));
|
|||
|
params.addElement(new Integer(3));
|
|||
|
|
|||
|
// Call the server, and get our result.
|
|||
|
Hashtable result =
|
|||
|
(Hashtable) server.execute("sample.sumAndDifference", params);
|
|||
|
int sum = ((Integer) result.get("sum")).intValue();
|
|||
|
int difference = ((Integer) result.get("difference")).intValue();
|
|||
|
|
|||
|
// Print out our result.
|
|||
|
System.out.println("Sum: " + Integer.toString(sum) +
|
|||
|
", Difference: " +
|
|||
|
Integer.toString(difference));
|
|||
|
|
|||
|
} catch (XmlRpcException exception) {
|
|||
|
System.err.println("JavaClient: XML-RPC Fault #" +
|
|||
|
Integer.toString(exception.code) + ": " +
|
|||
|
exception.toString());
|
|||
|
} catch (Exception exception) {
|
|||
|
System.err.println("JavaClient: " + exception.toString());
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
9.2. A Stand-Alone Java Server
|
|||
|
|
|||
|
Save the following program in a file named JavaServer.java.
|
|||
|
import java.util.Hashtable;
|
|||
|
import helma.xmlrpc.*;
|
|||
|
|
|||
|
public class JavaServer {
|
|||
|
|
|||
|
public JavaServer () {
|
|||
|
// Our handler is a regular Java object. It can have a
|
|||
|
// constructor and member variables in the ordinary fashion.
|
|||
|
// Public methods will be exposed to XML-RPC clients.
|
|||
|
}
|
|||
|
|
|||
|
public Hashtable sumAndDifference (int x, int y) {
|
|||
|
Hashtable result = new Hashtable();
|
|||
|
result.put("sum", new Integer(x + y));
|
|||
|
result.put("difference", new Integer(x - y));
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
public static void main (String [] args) {
|
|||
|
try {
|
|||
|
|
|||
|
// Invoke me as <http://localhost:8080/RPC2>.
|
|||
|
WebServer server = new WebServer(8080);
|
|||
|
server.addHandler("sample", new JavaServer());
|
|||
|
|
|||
|
} catch (Exception exception) {
|
|||
|
System.err.println("JavaServer: " + exception.toString());
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
10. Using XML-RPC with PHP
|
|||
|
|
|||
|
Edd Dumbill has implemented XML-RPC for PHP. You can download it from the
|
|||
|
UsefulInc XML-RPC website.
|
|||
|
|
|||
|
To install the distribution, decompress it and copy xmlrpc.inc and
|
|||
|
xmlrpcs.inc into the same directory as your PHP scripts.
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
10.1. A PHP Client
|
|||
|
|
|||
|
The following script shows how to embed XML-RPC calls into a web page.
|
|||
|
<html>
|
|||
|
<head>
|
|||
|
<title>XML-RPC PHP Demo</title>
|
|||
|
</head>
|
|||
|
<body>
|
|||
|
<h1>XML-RPC PHP Demo</h1>
|
|||
|
|
|||
|
<?php
|
|||
|
include 'xmlrpc.inc';
|
|||
|
|
|||
|
// Make an object to represent our server.
|
|||
|
$server = new xmlrpc_client('/api/sample.php',
|
|||
|
'xmlrpc-c.sourceforge.net', 80);
|
|||
|
|
|||
|
// Send a message to the server.
|
|||
|
$message = new xmlrpcmsg('sample.sumAndDifference',
|
|||
|
array(new xmlrpcval(5, 'int'),
|
|||
|
new xmlrpcval(3, 'int')));
|
|||
|
$result = $server->send($message);
|
|||
|
|
|||
|
// Process the response.
|
|||
|
if (!$result) {
|
|||
|
print "<p>Could not connect to HTTP server.</p>";
|
|||
|
} elseif ($result->faultCode()) {
|
|||
|
print "<p>XML-RPC Fault #" . $result->faultCode() . ": " .
|
|||
|
$result->faultString();
|
|||
|
} else {
|
|||
|
$struct = $result->value();
|
|||
|
$sumval = $struct->structmem('sum');
|
|||
|
$sum = $sumval->scalarval();
|
|||
|
$differenceval = $struct->structmem('difference');
|
|||
|
$difference = $differenceval->scalarval();
|
|||
|
print "<p>Sum: " . htmlentities($sum) .
|
|||
|
", Difference: " . htmlentities($difference) . "</p>";
|
|||
|
}
|
|||
|
?>
|
|||
|
|
|||
|
</body></html>
|
|||
|
|
|||
|
If your webserver doesn't run PHP scripts, see the [http://www.php.net/] PHP
|
|||
|
website for more information.
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
10.2. A PHP Server
|
|||
|
|
|||
|
The following script shows how to implement an XML-RPC server using PHP.
|
|||
|
<?php
|
|||
|
include 'xmlrpc.inc';
|
|||
|
include 'xmlrpcs.inc';
|
|||
|
|
|||
|
function sumAndDifference ($params) {
|
|||
|
|
|||
|
// Parse our parameters.
|
|||
|
$xval = $params->getParam(0);
|
|||
|
$x = $xval->scalarval();
|
|||
|
$yval = $params->getParam(1);
|
|||
|
$y = $yval->scalarval();
|
|||
|
|
|||
|
// Build our response.
|
|||
|
$struct = array('sum' => new xmlrpcval($x + $y, 'int'),
|
|||
|
'difference' => new xmlrpcval($x - $y, 'int'));
|
|||
|
return new xmlrpcresp(new xmlrpcval($struct, 'struct'));
|
|||
|
}
|
|||
|
|
|||
|
// Declare our signature and provide some documentation.
|
|||
|
// (The PHP server supports remote introspection. Nifty!)
|
|||
|
$sumAndDifference_sig = array(array('struct', 'int', 'int'));
|
|||
|
$sumAndDifference_doc = 'Add and subtract two numbers';
|
|||
|
|
|||
|
new xmlrpc_server(array('sample.sumAndDifference' =>
|
|||
|
array('function' => 'sumAndDifference',
|
|||
|
'signature' => $sumAndDifference_sig,
|
|||
|
'docstring' => $sumAndDifference_doc)));
|
|||
|
?>
|
|||
|
|
|||
|
You would normally invoke this as something like http://localhost/path/
|
|||
|
sumAndDifference.php.
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
11. Using XML-RPC with Microsoft .NET
|
|||
|
|
|||
|
Charles Cook is writing an excellent new chapter for this HOWTO. You can find
|
|||
|
a draft online. If that page disappears, look for a new version of the
|
|||
|
XML-RPC HOWTO at the Linux Documentation Project.
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
12. Using XML-RPC with Ruby
|
|||
|
|
|||
|
(This section of the XML-RPC HOWTO was generously provided by Michael
|
|||
|
Neumann.)
|
|||
|
|
|||
|
[http://www.ruby-lang.org/] Ruby is an object-oriented scripting language. It
|
|||
|
already has a major following in Japan, and it's becoming popular elsewhere.
|
|||
|
|
|||
|
To use XML-RPC with Ruby, you must first install Yoshida Masato's xmlparser
|
|||
|
module (a wrapper for James Clark's expat parser). This can be found at the
|
|||
|
Ruby Application Archive.
|
|||
|
|
|||
|
Then, you must install [http://www.s-direktnet.de/homepages/neumann/xmlrpc4r/
|
|||
|
index.html] xmlrpc4r using the following commands:
|
|||
|
bash$ tar -xvzf xmlrpc4r-1_2.tar.gz
|
|||
|
bash$ cd xmlrpc4r-1_2
|
|||
|
bash$ su root -c "ruby install.rb"
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
12.1. A Ruby Client
|
|||
|
|
|||
|
Here's a simple Ruby client:
|
|||
|
require "xmlrpc/client"
|
|||
|
|
|||
|
# Make an object to represent the XML-RPC server.
|
|||
|
server = XMLRPC::Client.new( "xmlrpc-c.sourceforge.net", "/api/sample.php")
|
|||
|
|
|||
|
# Call the remote server and get our result
|
|||
|
result = server.call("sample.sumAndDifference", 5, 3)
|
|||
|
|
|||
|
sum = result["sum"]
|
|||
|
difference = result["difference"]
|
|||
|
|
|||
|
puts "Sum: #{sum}, Difference: #{difference}"
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
12.2. A Ruby Server
|
|||
|
|
|||
|
Here's a simple Ruby server:
|
|||
|
require "xmlrpc/server"
|
|||
|
|
|||
|
s = XMLRPC::CGIServer.new
|
|||
|
|
|||
|
s.add_hanlder("sample.sumAndDifference") do |a,b|
|
|||
|
{ "sum" => a + b, "difference" => a - b }
|
|||
|
end
|
|||
|
|
|||
|
s.serve
|
|||
|
|
|||
|
This could also have been written as follows:
|
|||
|
require "xmlrpc/server"
|
|||
|
|
|||
|
s = XMLRPC::CGIServer.new
|
|||
|
|
|||
|
class MyHandler
|
|||
|
def sumAndDifference(a, b)
|
|||
|
{ "sum" => a + b, "difference" => a - b }
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
s.add_handler("sample", MyHandler.new)
|
|||
|
s.serve
|
|||
|
|
|||
|
To run either server in standalone mode, replace the second line of code with
|
|||
|
the following:
|
|||
|
s = XMLRPC::Server.new(8080)
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
13. Using XML-RPC with Proprietary Languages
|
|||
|
|
|||
|
Implementations of XML-RPC are available for the following proprietary
|
|||
|
programming languages and environments.
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
13.1. Using XML-RPC with K
|
|||
|
|
|||
|
(This section of the XML-RPC HOWTO was generously provided by Christian
|
|||
|
Langreiter.)
|
|||
|
|
|||
|
[http://www.kx.com/] K is a language used in finance and database
|
|||
|
development. To install XML-RPC for K, download it from the Kx website.
|
|||
|
Uncompress and copy the files into the directory in which you keep your .k
|
|||
|
programs.
|
|||
|
|
|||
|
Here's a short client:
|
|||
|
\l kxr
|
|||
|
server:("localhost";"/cgi-bin/sumAndDifference.cgi");
|
|||
|
.kxr.c[server;"sumAndDifference";2 3]
|
|||
|
|
|||
|
And here's a server:
|
|||
|
\l kxrsc
|
|||
|
.kxr.sm: ,("sumAndDifference";{.((`sum;+/x);(`difference;-/x))})
|
|||
|
|
|||
|
More examples are included in the distribution.
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
14. Applications with Built-in XML-RPC Support
|
|||
|
|
|||
|
Several popular Linux applications include support for XML-RPC. These have
|
|||
|
already been described elsewhere, so we mostly provide pointers to articles.
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
14.1. Zope
|
|||
|
|
|||
|
Articles on using XML-RPC with Zope are available elsewhere on the web:
|
|||
|
|
|||
|
<EFBFBD><EFBFBD>*<2A>XML-RPC Programming with Zope by Jon Udell
|
|||
|
|
|||
|
<EFBFBD><EFBFBD>*<2A>Zope XML-RPC at UserLand.Com
|
|||
|
|
|||
|
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
14.2. KDE 2.0
|
|||
|
|
|||
|
KDE 2.0 includes Kurt Ganroth's kxmlrpc daemon, which allows you to script
|
|||
|
KDE applications using XML-RPC.
|
|||
|
|
|||
|
Here's a short sample application in Python. It shows you how to connect to
|
|||
|
kxmlrpc, manipulate your KDE address book, and query the KDE trader.
|
|||
|
|
|||
|
If you have any other articles or example code, please see Section 15.3. We'd
|
|||
|
like to have more information on scripting KDE.
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
15. About This Document
|
|||
|
|
|||
|
This document is part of the Linux Documentation Project. Thanks go to Dave
|
|||
|
Winer and maintainers of all the various XML-RPC libraries.
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
15.1. New Versions of This Document
|
|||
|
|
|||
|
New versions of this document are available at the Linux Documentation
|
|||
|
Project website.
|
|||
|
|
|||
|
They also provide this manual in alternate formats, including [http://
|
|||
|
www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/pdf/XML-RPC-HOWTO.pdf]
|
|||
|
PDF, gzipped HTML and ASCII text.
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
15.2. Contributors to the XML-RPC HOWTO
|
|||
|
|
|||
|
The section on Ruby was contributed by Michael Neumann (neumann AT
|
|||
|
s-direktnet DOT de). The section on K was contributed by Christian Langreiter
|
|||
|
(c DOT langreiter AT synerge DOT at).
|
|||
|
|
|||
|
These contributors are all credited at the beginning of their sections.
|
|||
|
-----------------------------------------------------------------------------
|
|||
|
|
|||
|
15.3. Submitting Other Snippets
|
|||
|
|
|||
|
If you have a sample client or server in another language or environment,
|
|||
|
we'd love to include it in this manual. To add a new entry, we need the
|
|||
|
following information:
|
|||
|
|
|||
|
<EFBFBD><EFBFBD>*<2A>The URL of the XML-RPC implementation used.
|
|||
|
|
|||
|
<EFBFBD><EFBFBD>*<2A>Installation instructions.
|
|||
|
|
|||
|
<EFBFBD><EFBFBD>*<2A>A complete, runnable program.
|
|||
|
|
|||
|
<EFBFBD><EFBFBD>*<2A>Compilation instructions, if applicable.
|
|||
|
|
|||
|
|
|||
|
E-mail your example to the xmlrpc-c-devel mailing list or directly to
|
|||
|
[mailto:eric.kidd@pobox.com] Eric Kidd.
|
|||
|
|
|||
|
Thank you for your help!
|