La biblioteca XML-RPC que se encuentra en Internet es muy útil para desarrollar pequeñas interfaces de comunicación externa. Guarde este código como xml-rpc.inc.php
<?php.
/*
La biblioteca XML-RPC que se encuentra en Internet es muy útil para desarrollar pequeñas interfaces de comunicación externa.
*/
función & XML_serialize($datos, $nivel = 0, $prior_key = NULL){
#asume un hash, las claves son los nombres de las variables
$xml_serialized_string = "";
while(lista($clave, $valor) = cada uno($datos)){
$en línea = falso;
$matriz_numérica = falso;
$atributos = "";
#echo "Mi clave actual es '$key', llamada con la clave anterior '$prior_key'<br>";
if(!strstr($key, "attr")){ #si no es un atributo
if(array_key_exists("$atributo clave", $datos)){
while(lista($attr_name, $attr_value) = cada($datos["$key attr"])){
#echo "Se encontró el atributo $attribute_name con valor $attribute_value<br>";
$attr_value = &htmlspecialchars($attr_value, ENT_QUOTES);
$atributos .= " $attr_name="$attr_value"";
}
}
si(is_numeric($clave)){
#echo "Mi clave actual ($key) es numérica. Mi clave principal es '$prior_key'<br>";
$clave = $clave_anterior;
}demás{
#no puedes tener teclas numéricas en dos niveles seguidos, así que está bien
#echo "Comprobando si existe una clave numérica en los datos.";
if(is_array($valor) y array_key_exists(0, $valor)){
# echo "¡Así es! Llamándome a mí mismo como resultado de una matriz numérica.<br>";
$numeric_array = verdadero;
$xml_serialized_string .= XML_serialize($valor, $nivel, $clave);
}
#echo "<br>";
}
si(!$numeric_array){
$xml_serialized_string .= str_repeat("t", $nivel) "<$clave$atributos>";
si(is_array($valor)){
$xml_serialized_string .= "rn" XML_serialize($valor, $nivel+1);
}demás{
$en línea = verdadero;
$xml_serialized_string .= htmlspecialchars($valor);
}
$xml_serialized_string .= (!$inline ? str_repeat("t", $level) : "") "</$key>rn";
}
}demás{
#echo "Omitir registro de atributo para la clave $key<bR>";
}
}
si($nivel == 0){
$xml_serialized_string = "<?xml version="1.0" ?>rn" $xml_serialized_string;
devolver $xml_serialized_string;
}demás{
devolver $xml_serialized_string;
}
}
clase XML {
var $parser; #una referencia al analizador XML
var $document; #toda la estructura XML creada hasta el momento
var $current; #un puntero al elemento actual: ¿qué es esto?
var $parent; #un puntero al padre actual - el padre será una matriz
var $parents; #una matriz del padre más reciente en cada nivel
var $última_etiqueta_abierta;
función XML($datos=nulo){
$this->parser = xml_parser_create();
xml_parser_set_option ($this->parser, XML_OPTION_CASE_FOLDING, 0);
xml_set_object($this->parser, $this);
xml_set_element_handler($this->parser, "abrir", "cerrar");
xml_set_character_data_handler($this->parser, "datos");
# Register_shutdown_function(array($this, 'destruct'));
}
función destruir(){
xml_parser_free($this->parser);
}
análisis de función ($datos){
$this->documento = matriz();
$este->padre = $este->documento;
$this->padres = matriz();
$this->last_opened_tag = NULL;
xml_parse($this->parser, $datos);
devolver $este->documento;
}
función abierta($analizador, $etiqueta, $atributos){
#echo "Etiqueta de apertura $etiqueta<br>n";
$this->datos = "";
$this->last_opened_tag = $etiqueta #etiqueta es una cadena
if(array_key_exists($etiqueta, $this->padre)){
#echo "Ya existe una instancia de '$tag' en el nivel actual ($level)<br>n";
if(is_array($this->parent[$tag]) and array_key_exists(0, $this->parent[$tag])){ #si las claves son numéricas
#necesitamos asegurarnos de que sean numéricos (tener en cuenta los atributos)
$clave = count_numeric_items($this->parent[$tag]);
#echo "Hay instancias de $key: las claves son numéricas.<br>n";
}demás{
#echo "Sólo hay una instancia. Cambiando todo de lugar<br>n";
$temp = $this->parent[$etiqueta];
unset($this->padre[$etiqueta]);
$this->parent[$tag][0] = $temp;
if(array_key_exists("$etiqueta atributo", $this->parent)){
#cambia los atributos también si existen
$temp = $this->parent["$atributo de etiqueta"];
unset($this->parent["$atributo de etiqueta"]);
$this->parent[$tag]["0 attr"] = $temp;
}
$clave = 1;
}
$this->padre = $this->parent[$etiqueta];
}demás{
$clave = $etiqueta;
}
si($atributos){
$this->parent["$key attr"] = $atributos;
}
$this->parent[$key] = matriz();
$this->padre = $this->parent[$key];
array_unshift($esto->padres, $esto->padre);
}
datos de función ($ analizador, $ datos) {
#echo "Los datos son '", htmlspecialchars($datos), "'<br>n";
if($this->last_opened_tag != NULL){
$esto->datos .= $datos;
}
}
función cerrar ($ analizador, $ etiqueta) {
#echo "Cerrar etiqueta $etiqueta<br>n";
if($this->last_opened_tag == $etiqueta){
$esto->padre = $esto->datos;
$this->last_opened_tag = NULL;
}
array_shift($this->padres);
$esto->padre = $esto->padres[0];
}
}
función & XML_unserialize($xml){
$xml_parser = nuevo XML();
$datos = $xml_parser->parse($xml);
$xml_parser->destruct();
devolver $datos;
}
función & XMLRPC_parse($solicitud){
si(definido('XMLRPC_DEBUG') y XMLRPC_DEBUG){
XMLRPC_debug('XMLRPC_parse', "<p>Recibió la siguiente solicitud sin formato:</p>" . XMLRPC_show($request, 'print_r', true));
}
$datos = &XML_unserialize($solicitud);
si(definido('XMLRPC_DEBUG') y XMLRPC_DEBUG){
XMLRPC_debug('XMLRPC_parse', "<p>Devolviendo la siguiente solicitud analizada:</p>" . XMLRPC_show($data, 'print_r', true));
}
devolver $datos;
}
función & XMLRPC_prepare($datos, $tipo = NULL){
si(is_array($datos)){
$num_elementos = recuento($datos);
if((array_key_exists(0, $data) o !$num_elements) y $type != 'struct'){ #es una matriz
if(!$num_elements){ #si la matriz está vacía
$ valor de retorno = matriz ('matriz' => matriz ('datos' => NULL));
}demás{
$returnvalue['matriz']['datos']['valor'] = matriz();
$temp = $returnvalue['matriz']['datos']['valor'];
$cuenta = count_numeric_items($datos);
para($n=0; $n<$cuenta; $n++){
$tipo = NULO;
if(array_key_exists("$n tipo", $datos)){
$tipo = $datos["$n tipo"];
}
$temp[$n] = XMLRPC_prepare($datos[$n], $tipo);
}
}
}else{ #es una estructura
if(!$num_elements){ #si la estructura está vacía
$returnvalue = array('struct' => NULL);
}demás{
$returnvalue['struct']['member'] = matriz();
$temp = $returnvalue['struct']['member'];
while(lista($clave, $valor) = cada uno($datos)){
if(substr($key, -5) != 'type'){ #si no es un especificador de tipo
$tipo = NULO;
if(array_key_exists("$tipo de clave", $datos)){
$tipo = $datos["$tipo de clave"];
}
$temp[] = array('nombre' => $clave, 'valor' => XMLRPC_prepare($valor, $tipo));
}
}
}
}
}else{ #es un escalar
si(!$tipo){
si(is_int($datos)){
$valorretorno['int'] = $datos;
devolver $ valor de retorno;
}elseif(is_float($datos)){
$valorderetorno['doble'] = $datos;
devolver $ valor de retorno;
}elseif(is_bool($datos)){
$returnvalue['boolean'] = ($datos? 1: 0);
devolver $ valor de retorno;
}elseif(preg_match('/^d{8}Td{2}:d{2}:d{2}$/', $data, $matches)){ #es una cita
$returnvalue['dateTime.iso8601'] = $datos;
devolver $ valor de retorno;
}elseif(is_string($datos)){
$returnvalue['cadena'] = htmlspecialchars($datos);
devolver $ valor de retorno;
}
}demás{
$valor de retorno[$tipo] = htmlspecialchars($datos);
}
}
devolver $ valor de retorno;
}
función & XMLRPC_adjustValue($current_node){
si(is_array($current_node)){
si(isset($current_node['array'])){
if(!is_array($current_node['array']['datos'])){
#Si no hay elementos, devuelve una matriz vacía
devolver matriz();
}demás{
#echo "Deshacerse de la matriz -> datos -> valor<br>n";
$temp = $current_node['matriz']['datos']['valor'];
if(is_array($temp) y array_key_exists(0, $temp)){
$cuenta = cuenta($temp);
para($n=0;$n<$cuenta;$n++){
$temp2[$n] = &XMLRPC_adjustValue($temp[$n]);
}
$temperatura = $temp2;
}demás{
$temp2 = &XMLRPC_adjustValue($temp);
$temp = matriz($temp2);
#Hago la tarea temporal porque evita copiar,
# ya que puedo poner una referencia en el array
El modelo de referencia de #PHP es un poco tonto y no puedo decir simplemente:
# $temp = array(&XMLRPC_adjustValue($temp));
}
}
}elseif(isset($current_node['struct'])){
si(!is_array($current_node['struct'])){
#Si no hay miembros, devuelve una matriz vacía
devolver matriz();
}demás{
#echo "Deshacerse de estructura -> miembro<br>n";
$temp = $current_node['struct']['miembro'];
if(is_array($temp) y array_key_exists(0, $temp)){
$cuenta = cuenta($temp);
para($n=0;$n<$cuenta;$n++){
#echo "Pasando el nombre {$temp[$n][nombre]}. El valor es: " . show($temp[$n][valor], var_dump, true) "<br>n";
$temp2[$temp[$n]['nombre']] = &XMLRPC_adjustValue($temp[$n]['valor']);
#echo "adjustValue(): Después de la asignación, el valor es " . show($temp2[$temp[$n]['name']], var_dump, true) "<br>n";
}
}demás{
#echo "Pasando nombre $temp[nombre]<br>n";
$temp2[$temp['nombre']] = &XMLRPC_adjustValue($temp['valor']);
}
$temperatura = $temp2;
}
}demás{
$tipos = array('cadena', 'int', 'i4', 'doble', 'dateTime.iso8601', 'base64', 'boolean');
$fall_through = verdadero;
foreach($tipos como $tipo){
if(array_key_exists($tipo, $current_node)){
#echo "Deshacerse de '$type'<br>n";
$temp = $nodo_actual[$tipo];
#echo "adjustValue(): El nodo actual está configurado con un tipo de $type<br>n";
$fall_through = falso;
romper;
}
}
si($cayó_a través){
$tipo = 'cadena';
#echo "¡Falló! El tipo es $tipo<br>n";
}
cambiar ($tipo){
caso 'int': caso 'i4': $temp = (int)$temp break;
caso 'cadena': $temp = (cadena)$temp;
caso 'doble': $temp = (doble)$temp;
caso 'booleano': $temp = (bool)$temp;
}
}
}demás{
$temp = (cadena)$current_node;
}
devolver $temperatura;
}
función XMLRPC_getParams($solicitud){
if(!is_array($request['methodCall']['params'])){
#Si no hay parámetros, devuelve una matriz vacía
devolver matriz();
}demás{
#echo "Deshacerse de métodoCall -> params -> param<br>n";
$temp = $request['methodCall']['params']['param'];
if(is_array($temp) y array_key_exists(0, $temp)){
$cuenta = cuenta($temp);
para($n = 0; $n < $cuenta; $n++){
#echo "Parámetro de serialización $n<br>";
$temp2[$n] = &XMLRPC_adjustValue($temp[$n]['valor']);
}
}demás{
$temp2[0] = &XMLRPC_adjustValue($temp['valor']);
}
$temperatura = $temp2;
devolver $temperatura;
}
}
función XMLRPC_getMethodName($methodCall){
#devuelve el nombre del método
return $llamadamétodo['llamadamétodo']['nombremétodo'];
}
función XMLRPC_request($sitio, $ubicación, $nombremétodo, $params = NULL, $user_agent = NULL){
$sitio = explotar(':', $sitio);
if(isset($sitio[1]) y is_numeric($sitio[1])){
$puerto = $sitio[1];
}demás{
$puerto = 80;
}
$sitio = $sitio[0];
$datos["methodCall"]["methodName"] = $methodName;
$param_count = recuento($params);
si(!$param_count){
$datos["methodCall"]["params"] = NULL;
}demás{
para($n = 0; $n<$param_count; $n++){
$datos["methodCall"]["params"]["param"][$n]["valor"] = $params[$n];
}
}
$datos = XML_serialize($datos);
si(definido('XMLRPC_DEBUG') y XMLRPC_DEBUG){
XMLRPC_debug('XMLRPC_request', "<p>Recibió la siguiente lista de parámetros para enviar:</p>" . XMLRPC_show($params, 'print_r', true));
}
$conn = fsockopen ($sitio, $puerto);
if(!$conn){ #si la conexión no se abrió correctamente
si(definido('XMLRPC_DEBUG') y XMLRPC_DEBUG){
XMLRPC_debug('XMLRPC_request', "<p>Error de conexión: no se pudo establecer la conexión con $site.</p>");
}
return array(false, array('faultCode'=>10532, 'faultString'=>"Error de conexión: no se pudo establecer la conexión con $site."));
}demás{
$encabezados =
"POST $ubicación HTTP/1.0rn".
"Anfitrión: $sitiorn".
"Conexión: cerrarrn".
($user_agent ? "Usuario-Agente: $user_agentrn" : '') .
"Tipo de contenido: texto/xmlrn".
"Longitud del contenido: " . strlen($datos) "rnrn";
fputs($conexión, "$encabezados");
fputs($conexión, $datos);
si(definido('XMLRPC_DEBUG') y XMLRPC_DEBUG){
XMLRPC_debug('XMLRPC_request', "<p>Envió la siguiente solicitud:</p>nn" . XMLRPC_show($headers . $data, 'print_r', true));
}
#socket_set_blocking ($conexión, falso);
$respuesta = "";
mientras(!feof($conn)){
$respuesta .= fgets($conn, 1024);
}
fclose($conexión);
#quitar encabezados de la respuesta
$datos = XML_unserialize(substr($respuesta, strpos($respuesta, "rnrn")+4));
si(definido('XMLRPC_DEBUG') y XMLRPC_DEBUG){
XMLRPC_debug('XMLRPC_request', "<p>Recibió la siguiente respuesta:</p>nn" . XMLRPC_show($response, 'print_r', true). "<p>Que fue serializado en los siguientes datos:< /p>nn" . XMLRPC_show($datos, 'print_r', verdadero));
}
if(isset($datos['métodoRespuesta']['fallo'])){
$return = array(false, XMLRPC_adjustValue($data['methodResponse']['fault']['value']));
si(definido('XMLRPC_DEBUG') y XMLRPC_DEBUG){
XMLRPC_debug('XMLRPC_request', "<p>Volviendo:</p>nn" . XMLRPC_show($return, 'var_dump', true));
}
devolver $regresar;
}demás{
$return = array(true, XMLRPC_adjustValue($data['methodResponse']['params']['param']['value']));
si(definido('XMLRPC_DEBUG') y XMLRPC_DEBUG){
XMLRPC_debug('XMLRPC_request', "<p>Volviendo:</p>nn" . XMLRPC_show($return, 'var_dump', true));
}
devolver $regresar;
}
}
}
función XMLRPC_response($return_value, $servidor = NULL){
$datos["methodResponse"]["params"]["param"]["value"] = $return_value;
$retorno = XML_serialize($datos);
si(definido('XMLRPC_DEBUG') y XMLRPC_DEBUG){
XMLRPC_debug('XMLRPC_response', "<p>Recibimos los siguientes datos para devolver:</p>nn" . XMLRPC_show($return_value, 'print_r', true));
}
encabezado("Conexión: cerrar");
header("Contenido-Longitud: " . strlen($return));
encabezado("Tipo de contenido: texto/xml");
encabezado("Fecha: " . fecha("r"));
si($servidor){
encabezado("Servidor: $servidor");
}
si(definido('XMLRPC_DEBUG') y XMLRPC_DEBUG){
XMLRPC_debug('XMLRPC_response', "<p>Envió la siguiente respuesta:</p>nn" . XMLRPC_show($return, 'print_r', true));
}
eco $retorno;
}
función XMLRPC_error($faultCode, $faultString, $servidor = NULL){
$matriz["methodResponse"]["fault"]["value"]["struct"]["member"] = array();
$temp = $array["methodResponse"]["fault"]["value"]["struct"]["member"];
$temp[0]["nombre"] = "código de error";
$temp[0]["valor"]["int"] = $códigodefallo;
$temp[1]["nombre"] = "faultString";
$temp[1]["valor"]["cadena"] = $faultString;
$retorno = XML_serialize($matriz);
encabezado("Conexión: cerrar");
header("Contenido-Longitud: " . strlen($return));
encabezado("Tipo de contenido: texto/xml");
encabezado("Fecha: " . fecha("r"));
si($servidor){
encabezado("Servidor: $servidor");
}
si(definido('XMLRPC_DEBUG') y XMLRPC_DEBUG){
XMLRPC_debug('XMLRPC_error', "<p>Envió la siguiente respuesta de error:</p>nn" . XMLRPC_show($return, 'print_r', true));
}
eco $retorno;
}
función XMLRPC_convert_timestamp_to_iso8601($marca de tiempo){
#toma una marca de tiempo de Unix y la convierte a iso8601 requerido por XMLRPC
#un ejemplo de fecha y hora iso8601 es "20010822T03:14:33"
fecha de retorno("YmdTH:i:s", $marca de tiempo);
}
función XMLRPC_convert_iso8601_to_timestamp($iso8601){
return strtotime($iso8601);
}
función count_numeric_items($matriz){
return is_array($array)? count(array_filter(array_keys($array), 'is_numeric')): 0;
}
función XMLRPC_debug($nombre_función, $mensaje_depuración){
$GLOBALS['XMLRPC_DEBUG_INFO'][] = matriz($nombre_función, $mensaje_depuración);
}
función XMLRPC_debug_print(){
si($GLOBALS['XMLRPC_DEBUG_INFO']){
echo "<borde de la tabla="1" ancho="100%">n";
foreach($GLOBALS['XMLRPC_DEBUG_INFO'] como $depuración){
echo "<tr><th style="vertical-align: top">$debug[0]</th><td>$debug[1]</td></tr>n";
}
eco "</table>n";
unset($GLOBALS['XMLRPC_DEBUG_INFO']);
}demás{
echo "<p>Aún no hay información de depuración disponible.</p>";
}
}
función XMLRPC_show($datos, $func = "print_r", $return_str = false){
ob_start();
$func($datos);
$salida = ob_get_contents();
ob_end_clean();
si($return_str){
devolver "<pre>" htmlspecialchars($salida) "</pre>n";
}demás{
echo "<pre>", htmlspecialchars($salida), "</pre>n";
}
}
?>
Ejemplo de programa de servidor, server.php
<?
incluir 'xml-rpc.inc.php';
//Definir métodos que se pueden llamar de forma remota
$xmlrpc_methods=matriz();
$xmlrpc_methods['insertRecords']='insertRecords';
//Obtener el nombre del método y los parámetros pasados por el usuario
$xmlrpc_request = XMLRPC_parse($HTTP_RAW_POST_DATA);
$nombremétodo = XMLRPC_getMethodName($xmlrpc_request);
$params = XMLRPC_getParams($xmlrpc_request);
if (!isset($xmlrpc_methods[$nombredelmétodo])){
XMLRPC_error('1',"El método que llamaste no existe");
}demás {
$xmlrpc_methods[$nombredelmétodo]($params);
}
función insertarRecords($params){
si (emptyempty($params)){
XMLRPC_error('2',"Error de parámetro");
}
XMLRPC_response(XMLRPC_prepare('http://www.emtit.com'));
}
?>
Ejemplo de cliente PHP que llama al método del servidor
<?php
include_once 'xml-rpc.inc';
$params=array(2,3);
$result=XMLRPC_request("127.0.0.1","/services/server.php","insertRecords",$params);//El archivo del servidor se coloca en la carpeta de servicios
print_r($resultado);
?>