Viewing file: XmlRpcClient.py (6.56 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
######################################################################## # $Header: /var/local/cvsroot/4Suite/Ft/Server/Server/Xslt/XmlRpcClient.py,v 1.5 2005/04/06 23:05:46 jkloth Exp $ """ XSLT extensions allowing limited access to external XML-RPC servers
Copyright 2004 Fourthought, Inc. (USA). Detailed license and copyright information: http://4suite.org/COPYRIGHT Project home, documentation, distributions: http://4suite.org/ """
import xmlrpclib from Ft.Xml.XPath import Util from Ft.Xml.XPath import Conversions from Ft.Xml.Xslt import XsltElement from Ft.Xml.Xslt import ContentInfo, AttributeInfo from Ns import UTIL_NS
CONVERTERS_FROM_XSLT = { None: None, "INT": int, "DOUBLE": float, "BOOLEAN": lambda x: xmlrpclib.Boolean(not x and 1 or 0), "STRING": str, }
class XmlRpcInvokeElement(XsltElement): """ Invoke an XML-RPC server at a remote URI (Requires Python 2.2 or above) There are 5 attributes, p1, p2... which are used for the positional arguments to the remote method [this will be made less kludgy soon] Each one is an expression which follows the following conversion rules from the XPath data model:
string -> string number -> floating-point number boolean -> boolean node set -> array of strings
You can also coerce the value to a certain type by using an attribute of the form t1, t2,... corresponding to the pN attribute with one of the following string values:
INT DOUBLE STRING BOOLEAN
The return value is converted into an XML fragment representation, which is sent to output.
string -> <String>[value]</String> floating-point number -> <Double>[value]</Double> boolean -> boolean <Boolean>["true" or "false"]</Boolean> array -> <Array>[sequence of child elements as above, according to array elements]</Array>
An example of an array:
<Array> <String>a string</String> <Float>123.4</Float> <Int>1234</Int> <String>another string</String> </Array>
This means that in order to access a remote method
obj.spam('eggs', 3)
On a remote server at
http://spam.com/xmlrpcserver
And save the result of XSLT variable "monty", you can use the following XSLT snippet:
<xsl:variable name="monty"> <futil:xml-rpc-invoke uri="http://spam.com/xmlrpcserver" method="obj.spam" p1="'eggs'" p2="3" t2="INT"/> </xsl:variable>
No type coercion is used for p1 because XSLT string are generally unambiguous in converting to XML-RPC. However, the second param could be integer or double, so it is coerced (default is double).
Beware that if an array is returned, you might need to use the exslt:node-set function to convert from result tree fragment to node set. """
content = ContentInfo.Empty
legalAttrs = { 'uri' : AttributeInfo.UriReferenceAvt( required=1, description='The URI of the remote server'), 'method' : AttributeInfo.StringAvt( required=1, description='The method name to be invoked'), 'p1' : AttributeInfo.Expression( description='The first parameter for the remote server'), 't1' : AttributeInfo.Expression( description='Optional type spec for the first parameter'), 'p2' : AttributeInfo.Expression( description='The second parameter for the remote server'), 't2' : AttributeInfo.Expression( description='Optional type spec for the The second parameter'), 'p3' : AttributeInfo.Expression( description='The third parameter for the remote server'), 't3' : AttributeInfo.Expression( description='Optional type spec for the The third parameter'), 'p4' : AttributeInfo.Expression( description='The fourth parameter for the remote server'), 't4' : AttributeInfo.Expression( description='Optional type spec for the The fourth parameter'), 'p5' : AttributeInfo.Expression( description='The fifth parameter for the remote server'), 't5' : AttributeInfo.Expression( description='Optional type spec for the The fifth parameter'), }
_proxies = {}
def instantiate(self, context, processor): context.setProcessState(self)
uri = self._uri.evaluate(context) method_name = self._method.evaluate(context)
params = [] for i in range(1, 5): p = eval('self._p'+str(i)) t = eval('self._t'+str(i)) if p: p = p.evaluate(context) conv = CONVERTERS_FROM_XSLT[t and t.evaluate(context)] if conv: p = conv(p) params.append(p) print "Invoking XML-RPC method", method_name, "on server at", uri print "Parameters", params
if self._proxies.has_key(uri): proxy = self._proxies[uri] else: proxy = xmlrpclib.ServerProxy(uri) self._proxies[uri] = proxy method = getattr(proxy, method_name) results = method(*params) WriteXmlRpcResults(processor, results) return
def WriteXmlRpcResults(processor, results): if isinstance(results, list): processor.writers[-1].startElement(u'Array') for result in results: WriteXmlRpcResults(processor, results) processor.writers[-1].endElement(u'Array') elif isinstance(results, int): processor.writers[-1].startElement(u'Int') processor.writers[-1].text(str(results)) processor.writers[-1].endElement(u'Int') elif isinstance(results, float): processor.writers[-1].startElement(u'Double') processor.writers[-1].text(str(results)) processor.writers[-1].endElement(u'Double') elif isinstance(results, str): processor.writers[-1].startElement(u'String') processor.writers[-1].text(results) processor.writers[-1].endElement(u'String') elif isinstance(results, xmlrpclib.Boolean): processor.writers[-1].startElement(u'Boolean') processor.writers[-1].text(results and 'true' or 'false') processor.writers[-1].endElement(u'Boolean') elif isinstance(results, xmlrpclib.DateTime): processor.writers[-1].startElement(u'Date') processor.writers[-1].text(results.value) processor.writers[-1].endElement(u'Date') return
ExtFunctions = {}
ExtElements = { (UTIL_NS, 'xml-rpc-invoke'): XmlRpcInvokeElement, }
|