(W3C) SOAP is very like to XML-RPC and not the other way around.
It works by marshaling procedure calls over HTTP as XML documents. However, one major difference is that SOAP allows the documents to be treated literally as --- well, Documents.
As you will be able to see from the angle-brackets snippets below -- you will notice some major differences between SOAP and XML-RPC. One major difference you will notice right away is that XML-RPC doesnt have any of the XML Namespaces, doesnt support XML Schemas and has a very definite set of types and primitives. One of the major improvements of SOAP 1.2 over its preceding version is the removal of Section 5 Encoding, which, just like XML-RPC, is to improve the room for interoperablity by allowing people and parties to agree by having lesser opportunities for people to disagree (tm). I wont go much into details here. Eric Kidd has built up a fantastic repository about XML-RPC here.
As I have mentioned before, I had done some work before revolving around XML-RPC. In fact, I still see major operations out there still communicating via XML-RPC. While I love SOAP, XML-RPC still does get the job done if you wanted simplicity and faster interoperability. I am however, willing to bet that, as distributed computing really pushes the realm of distribution and enterprise requirements of Security, Transactions and Reliability becomes more deeply rooted in the message, SOAP will become the defacto standard in message transmission. In the same tone of distribution, I do still remember that while doing XML-RPC, while some people and companies will argue that it is a loose-coupled concept, it sure doesnt apply to the parties involved in the transactions and invocations. We spent unproductive hours on the phone and meeting tables arguing what should be sent over and many more over what it is supposed to look like on the wire. If weapons were allowed then, I am sure we would have reached an agreement faster. Of course, the weapons I meant here were things like the Colt .45 Pistol and the S&W .460 Magnum. Because, tools were more primitive then, we actually had to write every single element out before it goes onto the wire. Serialization was unheard of then.
I have built 3 simple Service Operations which is then broken into SOAP and XML-RPC Formats. The 3 methods and their I/Os are simple but they should be able to illustrate the different signatures and return types.
Function HelloWorld() As String...
Function SumAndDiff(ByVal x As Integer, ByVal y As Integer) As SumAndDiffStruc...
Function RetSoftwareDevelopers() As SoftwareDeveloper()...
These functions are then decorated with [XmlRpcMethod()] and [SoapMethod()] to distinguish themselves to their operation and binding approaches.
Let us see how each of them is represented differently on the wire. I will show the XML-RPC format first then followed by SOAP:
<methodCall>
<methodName>HelloWorld</methodName>
<params />
</methodCall>
<methodResponse>
<params>
<param>
<value>
<string>Hello World</string>
</value>
</param>
</params>
</methodResponse>
<methodCall>
<methodName>SumAndDiff</methodName>
<params>
<param>
<value>
<i4>15</i4>
</value>
</param>
<param>
<value>
<i4>10</i4>
</value>
</param>
</params>
</methodCall>
<methodResponse>
<params>
<param>
<value>
<struct>
<member>
<name>sum</name>
<value>
<i4>25</i4>
</value>
</member>
<member>
<name>diff</name>
<value>
<i4>5</i4>
</value>
</member>
</struct>
</value>
</param>
</params>
</methodResponse>
<methodCall>
<methodName>RetSoftwareDevelopers</methodName>
<params />
</methodCall>
<methodResponse>
<params>
<param>
<value>
<array>
<data>
<value>
<struct>
<member>
<name>Name</name>
<value>
<string>William Tay</string>
</value>
</member>
<member>
<name>Age</name>
<value>
<i4>30</i4>
</value>
</member>
<member>
<name>Profile</name>
<value>
<struct>
<member>
<name>Experience</name>
<value>
<i4>10</i4>
</value>
</member>
<member>
<name>Plaform</name>
<value>
<string>Microsoft .NET Technologies</string>
</value>
</member>
</struct>
</value>
</member>
</struct>
</value>
<value>
<struct>
<member>
<name>Name</name>
<value>
<string>ABC DEF GHI</string>
</value>
</member>
<member>
<name>Age</name>
<value>
<i4>50</i4>
</value>
</member>
<member>
<name>Profile</name>
<value>
<struct>
<member>
<name>Experience</name>
<value>
<i4>10</i4>
</value>
</member>
<member>
<name>Plaform</name>
<value>
<string>Microsoft .NET Technologies</string>
</value>
</member>
</struct>
</value>
</member>
</struct>
</value>
</data>
</array>
</value>
</param>
</params>
</methodResponse>
Below are the respective SOAP Representations:
<soap:Envelope xmlns:soap="..." xmlns:xsi="..." xmlns:xsd="...">
<soap:Body>
<HelloWorld xmlns="..." />
</soap:Body>
</soap:Envelope>
<soap:Envelope xmlns:soap="..." xmlns:xsi="..." xmlns:xsd="...">
<soap:Body>
<HelloWorldResponse xmlns="...">
<HelloWorldResult>Hello World</HelloWorldResult>
</HelloWorldResponse>
</soap:Body>
</soap:Envelope>
<soap:Envelope xmlns:soap="..." xmlns:xsi="..." xmlns:xsd="...">
<soap:Body>
<SumAndDiff xmlns="...">
<x>15</x>
<y>10</y>
</SumAndDiff>
</soap:Body>
</soap:Envelope>
<soap:Envelope xmlns:soap="..." xmlns:xsi="..." xmlns:xsd="...">
<soap:Body>
<SumAndDiffResponse xmlns="...">
<SumAndDiffResult>
<sum>25</sum>
<diff>5</diff>
</SumAndDiffResult>
</SumAndDiffResponse>
</soap:Body>
</soap:Envelope>
<soap:Envelope xmlns:soap="..." xmlns:xsi="..." xmlns:xsd="...">
<soap:Body>
<RetSoftwareDevelopers xmlns="..." />
</soap:Body>
</soap:Envelope>
<soap:Envelope xmlns:soap="..." xmlns:xsi="..." xmlns:xsd="...">
<soap:Body>
<RetSoftwareDevelopersResponse xmlns="...">
<RetSoftwareDevelopersResult>
<SoftwareDeveloper>
<Name>William Tay</Name>
<Age>30</Age>
<Profile>
<Experience>10</Experience>
<Plaform>Microsoft .NET Technologies</Plaform>
</Profile>
</SoftwareDeveloper>
<SoftwareDeveloper>
<Name>ABC DEF GHI</Name>
<Age>50</Age>
<Profile>
<Experience>10</Experience>
<Plaform>Microsoft .NET Technologies</Plaform>
</Profile>
</SoftwareDeveloper>
</RetSoftwareDevelopersResult>
</RetSoftwareDevelopersResponse>
</soap:Body>
</soap:Envelope>
As you would have noticed by now, XML-RPC has a fixed set of types and abstractions such as methodCall, methodName, params, value, struct, etc and of course, its response member-name-value pair. Like its name suggests, the param elements do represent each a parameter and the encapsulating structure does look like an object-instance representation. SOAP, on the other hand, makes heavy use of XML Namespaces and Schemas to validate how and what the message should look like.
We are, however, moving away from this RPC behaviour of transmission. This is a good thing as SOAP, while requiring much more engineering complexity, does offer much more extensibility in terms of message exchange patterns and extensible headers. Even the RPC-Encoding RPC-ish style messages that are generated by the SOAP toolkits of a couple of years back is making way for Document-Literal as the default style today. You take the messages "AS-IS" and how you mapped them into your platform native language and what you do with them is left to the implementation details of each platform. The XML schemas act as a way for you to tell what is legal or illegal as IO to your service.
Please note that I am using Charles Cook's fantastic XML-RPC .NET for my XML-RPC implementation here. Another way for you NOT to re-invent the wheel is to use Simon Fell's PocketXMLRPC. I am a huge fan of Simon Fell's SOAP Tools and I am sure this is a winner as well.