Sample Package
AnswerMe: XML-RPC <dateTime.iso8601> elements do not support timezones.
AnswerMe: missing a representation for ent:topic.
AnswerMe: how will this work with any SyntaxExtensionMechanism
<?xml version=\"1.0\" encoding=\"UTF-8\"?> < methodResponse> <params> <param> <value> <struct> <member> <name>title</name> <value> <string>My First Entry</string> </value> </member> <member> <name>summary</name> <value> <string>A very boring entry; just learning how to blog here...</string> </value> </member> <member> <name>author</name> <value> <struct> <member> <name>name</name> <value> <string>Bob B. Bobbington</string> </value> </member> <member> <name>homepage</name> <value> <string>http://bob.name/</string> </value> </member> <member> <name>weblog</name> <value> <string>http://bob.blog/</string> </value> </member> </struct> </value> </member> <member> <name>contributor</name> <value> <struct> <member> <name>name</name> <value> <string>Yo-Yo Dyne</string> </value> </member> <member> <name>homepage</name> <value> <string>http://yoyo.dyne.name/</string> </value> </member> <member> <name>weblog</name> <value> <string>http://blog.yoyo.dyne.name/</string> </value> </member> </struct> </value> </member> <member> <name>link</name> <value> <string>http://bob.blog/28</string> </value> </member> <member> <name>id</name> <value> <string>http://bob.blog/28</string> </value> </member> <member> <name>created</name> <value> <dateTime.iso8601>2003-02-05T12:29:29Z</dateTime.iso8601> </value> </member> <member> <name>issued</name> <value> <dateTime.iso8601>2003-02-05T08:29:29-04:00</dateTime.iso8601> </value> </member> <member> <name>modified</name> <value> <dateTime.iso8601>2003-02-05T12:29:29Z</dateTime.iso8601> </value> </member> <member> <name>content</name> <value> <string>Hello, <em>weblog</em> world! 2 < 4!</string> </value> </member> </struct> </value> </param> </params> </methodResponse>
Sample Call Using Toolkit
Cold Fusion
[RogerBenningfield, RefactorOk] In response to Sam's request in XmlRpcDiscussion, here's some ColdFusion code that returns an Echo feed to the client. Please note that it will generate a package that is slightly different than the above example. I've made every element a struct, while the example uses simple types for elements such as <title>. My way seems more consistent, but the example is pretty much in line with existing APIs, so maybe I'm nuts.
AnswerMe: the following does not put dates in an dateTime.iso8601.
-
[RogerBenningfield] Fixed.
AnswerMe: the 'ent' prefix in 'ent:topic' is associated with a namespace, where is that defined?
-
[RogerBenningfield] Fixed. Placed namespace declarations in a second, root-level struct.
<cfscript> myResponse = ArrayNew(1); myResponse[1] = StructNew(); myResponse[1].title.value = "My First Entry"; myResponse[1].summary.value = "A very boring entry; just learning how to blog here..."; myResponse[1].author.name.value = "Bob B. Bobbington"; myResponse[1].author.homepage.value = "http://bob.name/"; myResponse[1].author.weblog.value = "http://blog.yoyo.dyne.name/"; myResponse[1].contributor = ArrayNew(1); myResponse[1].contributor[1] = StructNew(); myResponse[1].contributor[1].name.value = "Yo-Yo Dyne"; myResponse[1].contributor[1].homepage.value = "http://yoyo.dyne.name/"; myResponse[1].contributor[1].name.value = "http://blog.yoyo.dyne.name/"; myResponse[1].link.value = "http://bob.blog/28"; myResponse[1].id.value = "http://bob.blog/28"; myResponse[1].created.value = "20030205T12:29:29"; myResponse[1].issued.value = "20030205T08:29:29"; myResponse[1].modified.value = "20030205T12:29:29"; myResponse[1].content = ArrayNew(1); myResponse[1].content[1] = StructNew(); myResponse[1].content[1].type = "application/xhtml+xml"; myResponse[1].content[1]["xml:lang"] = "en-us"; myResponse[1].content[1].value = "<p xmlns=""..."">Hello, <em>weblog</em> world! 2 < 4!</p>"; myResponse[1].content[2] = StructNew(); myResponse[1].content[2].type = "text/html"; myResponse[1].content[2]["xml:lang"] = "en-us"; myResponse[1].content[2].value = "<p>Hello, <em>weblog</em> world! 2 < 4!</p>"; myResponse[1].content[3] = StructNew(); myResponse[1].content[3].type = "text/plain"; myResponse[1].content[3]["xml:lang"] = "en-us"; myResponse[1].content[3].mode = "escaped"; myResponse[1].content[3].value = "Hello, _weblog_ world! 2 < 4!"; myResponse[1].content[4] = StructNew(); myResponse[1].content[4].type = "image/png"; myResponse[1].content[4]["xml:lang"] = "en-us"; myResponse[1].content[4].src = "http://bob.blog/helloworld.png"; myResponse[1]["ent:topic"] = StructNew(); myResponse[1]["ent:topic"].id = "introductory"; myResponse[1]["ent:topic"].value = "Hello"; myResponse[2].namespaces = StructNew(); myResponse[2].namespaces.ent = "http://www.purl.org/NET/ENT/1.0/"; </cfscript> <cfinvoke component="xmlrpc" method="CFML2XMLRPC" returnvariable="myResponsePackage" data="#myResponse#" lowercasenames="true" type="response">
Python
[GeorgBauer, RefactorOk] This is an example in python using the XML-RPC API. A SOAP call would look mostly the same. I still use the cleartext password stuff as most other XML-RPC APIs use, but it's not really necessary, you can quite easily use basic authentication or other stuff from your webserver. Or implement a challenge-response method based on XML-RPC calls (that's what I used in other places). The nice side of this for Python: I can work with internal data structures. I took some freedom to translate the XML into meaningfull structures, it's not necessarily this format, it could be different. For example I introduced a "value" element for those cases where I need to transport attributed tags and used the tags directly where there are nested tags. This is not the best way to do it, there are several problems with it (for example the conversion back to XML of unknown structure elements - you don't know wether the id and value of ent_topic are subelements or attributes, if you don't know about ent_topic's structure itself), it's just a sample to show how it _could_ look like.
-
[RogerBenningfield, RefactorOk] Georg: You're right about the potential pitfalls of "value", but it could just as easily be named "_value" or "xmlText" or something else that we can be reasonably sure won't be showing up as an attribute on any XML element.
-
[GeorgBauer, RefactorOk] I changed the sample a bit. Now the mapping is as follows: an element with just text is just mapped to a simple string. An element with attributes and a string is mapped to a structure where the attributes start with _ and namespaces are noted as _namespace_attribute and the value itself is noted as value_. An element with subelements is mapped to a structure with the tags as structure elements. Multiple values are represented as arrays. This allows to have an element with subelements, attributes and a value and to represent all this nicely. It's not meant to be a perfect and fully aesthetic mapping, it should be something that can be constructed automatically out of the XML text. This would allow to maintain RPC-type communication protocols automatically from the REST specification without any hassle and limitations to the REST specification. Should solve all problems at once
[MarkPilgrim] I've taken this mapping, applied it to Section 4.2 of Echo Api, and mocked up an apples-to-apples comparison between REST and XML-RPC of posting a new entry.
-
[AdriaanTijsseling] looks really good and illustrates Sam's point that translating from REST to XMLRPC won't be a big problem.
-
[JY] Mark's example shows that you have to find a toolkit to easily construct the data structure and then invoke an HTTP client. So the developer has to find such toolkits, and learn how to map XML. The XMLtramp page shows a list of similar implementations in a very few languages. There are tested XML-RPC clients for many environments. So, IMO, Mark's example uses the simplicity of xmltramp in Python, but implementing such toolkits in every environment would result in re-inventing XML-RPC (and XML-RPC takes care of the HTTP part too...). XML-RPC only deals with function calls and basic local data structures. Any developer can use that. No need to look at an XML file to construct a mapping.
-
It looks more like Georg is trying to recreate REST in XML-RPC. Passing all your arguments in a deeply nested structure with weird psuedo-namespace and pseudo-attribute mappings is obviously *not* what XML-RPC is designed for.
-
XML-RPC bindings are currently more widely available, but xmltramp is simpler and more widely useful than XML-RPC (it's good for all sorts of XML processing, not just remote procedure calls). Expect xmltramp-like interfaces to become more widespread once developers finally get tired of the awkwardness of the DOM.
-
[DannyAyers] Mark's example uses xmltramp, but aside from the possibility of tools like this in other languages, it would be straightforward to use DOM, perhaps with convenience wrappers. If we have a standard language in Necho, then we can have standard language bindings, and bypass XML-RPC. HTTP comms and XML tools are standard in modern languages. But having a logical XML representation in Necho and then using an arbitrary, unrelated language (XML-RPC) simply doesn't make sense. There is also a perhaps more fundamental point - using http in this fashion is very unweblike. Yes, it certainly is possible to use XML+http as an opaque transport. But it will be much easier for other systems to communicate with Necho tools if things are as transparent as possible (musing on this).
dateTime.iso8601 does not support timezones.
-
[AdriaanTijsseling] true. May need a different type for time encoding. One could even use a simple string as type, making sure the passed string value conforms to some date format supported by Echo.
-
Doesn't this negate the argument that XmlRpc is better because it handles datatypes for you?
-
[GeorgBauer] xmlrpclib.DateTime does support timezones. Maybe just adopt the format that is produced by this?
-
its support for timezones is not spec-compliant; it is implementation-dependent. The spec specifically states that dateTime.iso8601 does not support timezones, and that it is up to the client and server to work out timezone issues out-of-band (i.e. by a human being reading the server documentation).
-
[RogerBenningfield] In this case, the "server documentation" would be the Necho API specification, which could simply state that all XML-RPC datetime values are UTC.
-
Except that not all of them are. Some are preferred to be in the local timezone (issued).
import xmlrpclib srv = xmlrpclib.Server('http://some.connector.de/RPC2') item = { '_xmlns_ent': 'http://www.purl.org/NET/ENT/1.0/', 'title': 'some title', 'summary': 'the summary, quite boring stuff', 'author': { 'name': 'Georg Bauer', 'homepage': 'http://pyds.muensterland.org/', 'weblog': 'http://pyds.muensterland.org/weblog/' } 'contributor': [ { 'name': 'Phillip Pearson', 'homepage': 'http://pycs.net/', 'weblog': 'http://pycs.net/post/' } ], 'link': 'http://pyds.muensterland.org/weblog/2003/07/01.html#P999', 'id': 'P999', 'created': xmlrpclib.DateTime('2003-05-06T08:29:29-04:00'), 'issued': xmlrpclib.DateTime('2003-05-06T10:00:00Z'), 'modified': xmlrpclib.DateTime('2003-06-01T12:00:00Z'), 'content': [ { '_xml_lang': 'en-us', '_type': 'text/html', 'value_': '<p>This is a paragraph</p>' }, { '_xml_lang': 'en-us', '_type': 'text/plain', 'value_': 'This is a paragraph' } ] 'ent_topic': { '_id': 'introductory', 'value_': 'some value' } } srv.newPost(user, password, item)