Cómo escribir clientes XML-RPC

https://effbot.org/zone/element-xmlrpc.htm

==========

Uso de ElementTrees para generar mensajes XML-RPC

11 de julio de 2002 | Fredrik Lundh

Este es un trabajo en progreso.

El  protocolo XML-RPC  proporciona una manera simple de llamar a servicios remotos a través de una red. El protocolo se basa en estándares conocidos y ampliamente utilizados como HTTP y XML, y simplemente agrega una forma estándar de formatear solicitudes y paquetes de respuesta, y convertir valores de parámetros a XML y viceversa.

Para llamar a un servicio remoto, cree un documento XML que describa su solicitud de acuerdo con las instrucciones en la especificación XML-RPC, y use HTTP para publicarlo en el servidor. Si todo va bien, el servidor devolverá un documento XML que contiene la respuesta.

Aquí hay un ejemplo simple de solicitud (directamente de la especificación XML-RPC):

<? xml version = "1.0"?> 
<methodCall> 
  <methodName> examples.getStateName </methodName> 
  <params> 
    <param> 
      <value><i4>41</i4> </value> 
    </param> 
  </ params> 
</methodCall>

La solicitud consta de un  elemento methodCall de nivel  superior , que contiene dos subelementos,  methodName  y  params .

Como su nombre lo indica, el   elemento methodName contiene el nombre del procedimiento remoto a invocar. En este caso, el nombre es  examples.getStateName , que se puede interpretar como un   método getStateName proporcionado por el   servicio de ejemplos .

El   elemento params , finalmente, contiene parámetros para pasar al procedimiento. Debe contener varios   subelementos param , cada uno con un  valor . El   elemento params es opcional; Si el procedimiento no toma argumentos, puede omitirlo.

El siguiente script utiliza el   módulo httplib para enviar esta solicitud a un servidor userland.com:

Ejemplo: envío de una solicitud XML-RPC predefinida
host = "betty.userland.com" 

handler = "/ RPC2" 

body = "" "\ 
<? xml version =" 1.0 "?> 
<methodCall> 
  <methodName> examples.getStateName </methodName> 
  <params> 
    <param> 
      <value><i4>41</i4> </value> 
    </param> 
  </params> 
</methodCall> 
"" " def do_request (host, controlador, cuerpo): desde httplib import HTTP # send xml-rpc request h = HTTP (host) h.putrequest ( "POST", controlador) h.putheader ( "User-Agent", "element-xmlrpc") h.putheader ( "Host", host) h.putheader ( "Content-Type", "text / xml") h.putheader (



    "Content-Length", str (len (body))) h.endheaders () h.send (body) # busca la respuesta errcode, errmsg, headers = h.getreply () if errcode! = 200: raise Exception (errcode , errmsg) return h.getfile () print do_request (host, handler, body) .read ()

Suponiendo que  betty.userland.com  está en funcionamiento, el script anterior produce el siguiente resultado (o algo muy similar):

<? xml version = "1.0"?> 
<methodResponse> 
  <params> 
    <param> 
      <value> South Dakota </value> 
    </param> 
  </params> 
</methodResponse>

La respuesta es similar en estructura. El elemento toplevel nos dice que este es  methodResponse , y los valores de retorno se almacenan en un   elemento params .

Analizando la respuesta

En lugar de imprimir la respuesta, podemos analizarla en un  ElementTree y usar métodos de elementos estándar para acceder al contenido de la respuesta:

file = do_request (host, handler, body) import ElementTree 
tree = ElementTree.parse (file) 
methodResponse = tree.getroot () for param in methodResponse.find ( "params"): print repr (param [0] .text)




Si ejecuta este script, imprimirá  'Dakota del Sur'  (a menos que alguien haya movido las cosas, por supuesto).

Parámetros de codificación y valores de retorno

Ambos parámetros y valores de retorno siempre se almacenan en   elementos de valor , utilizando un subelemento para especificar tanto el tipo (en el campo de etiqueta) como el valor (como texto). Para las cadenas, puede omitir el subelemento y almacenar el valor de la cadena en el propio elemento de valor.

XML-RPC admite los siguientes elementos de tipo:

i4  o  int

Un entero con signo de 32 bits.

booleano

Un valor booleano, o marca: 0 para falso, 1 para verdadero.

cuerda

Una cadena de caracteres XML (consulte también  XML-RPC y la limitación ASCII ).

doble

Un número de coma flotante con signo de doble precisión (64 bits).

dateTime.iso8601

Fecha / hora dada como una cadena ISO 8601 de 17 caracteres: "aaaammddThh: mm: dd". Tenga en cuenta que el valor se da como un "tiempo ingenuo"; No incluye una zona horaria.

base64

Datos binarios, almacenados como texto codificado en base64

formación

Una colección ordenada de valores (similar a una lista de Python). El   elemento de matriz debe tener un subelemento denominado  datos , que puede contener cualquier cantidad de  subelementos de  valor . Las matrices se pueden anidar.

estructura

Una colección desordenada de pares cadena / valor (similar a un diccionario de Python). El   elemento struct puede contener cualquier número de   subelementos miembros , cada uno con un   elemento de nombre con la cadena de clave y un   elemento de valor que contiene el valor. Las estructuras se pueden anidar.

Continuará…


 

Notas:

El  módulo http_xml  contiene código para enviar y recibir árboles de elementos a través de HTTP.

El siguiente fragmento de código decodifica un argumento de valor, de forma recursiva:

desde base64 import decodestring 

unmarshallers = { "int": lambda x: int (x.text), "i4": lambda x: int (x.text), "boolean": lambda x: bool (int (x.text) ), "string": lambda x: x.text o "", "double": lambda x: float (x.text), "dateTime.iso8601": lambda x: datetime (x.text), "array": lambda x: [unmarshal (v) para v en x [0]], "struct": lambda x: dict ([(k.text o "", unmarshal (v)) para k, v en x]), " base64 ": lambda x:decodestring (x.text o "")} def
    unmarshal (elem): if elem: value = elem [0] return unmarshallers [value.tag] (value) return elem.text o ""

Aquí hay una versión alternativa de la línea de estructura, que también funciona en Python 2.1:

    "struct": lambda x: ([d para d en [{}]],  [d.setdefault (k.text o "", unmarshal (v)) para (k, v) en x], d) [2 ],

Hmm Tal vez debería comenzar con una versión un poco más legible, utilizando funciones separadas de arreglo de matriz y estructura de arreglo ...

Aquí hay un fragmento que crea una solicitud XML-RPC, con parámetros dados como una secuencia:

def marshal_method_call (method_name, params): 
    method_call_elem = Element ( "methodCall") 
    SubElement (method_call_elem, "methodName"). text = method_name si params:  params_elem = SubElement (method_call_elem, "params") para obtener el valor en params: Elem = Subm params_elem, "param") elem.append (marshal (value)) return method_call_elem

Y aquí hay un fragmento que crea una respuesta XML-RPC. Tenga en cuenta que un método solo puede devolver un valor único; para devolver múltiples valores, colóquelos en una tupla.

def marshal_method_response (params): 
    method_response_elem = Element ( "methodResponse") 
    param_elem = SubElement ( 
        SubElement (method_response_elem, "params"), "param"  )  param_elem.append (marshal (params)) return method_response_elem
    

Aquí hay una versión trozo de mariscal. Esta versión solo admite algunos tipos de datos:

marshallers = { 
    type (0): lambda x, v: (SubElement (x, "i4"), str (v)), 
    type (0.0): lambda x, v: (SubElement (x, "double"), str (v)),  escriba ( ""): lambda x, v: (SubElement (x, "string"), v)} def marshal (value): value_elem = Element ( "value") elem, elem.text = marshallers [type (value)] (value_elem, value) return value_elem
 

Supongo que te gusta

Origin www.cnblogs.com/kungfupanda/p/12749486.html
Recomendado
Clasificación