php xml-rpc远程调用


Posted in PHP onDecember 19, 2008
<?php 
/* 
从网上找来的XML-RPC库,对于开发小型的外部通讯接口很有用 
*/ function & XML_serialize($data, $level = 0, $prior_key = NULL){ 
#assumes a hash, keys are the variable names 
$xml_serialized_string = ""; 
while(list($key, $value) = each($data)){ 
$inline = false; 
$numeric_array = false; 
$attributes = ""; 
#echo "My current key is '$key', called with prior key '$prior_key'<br>"; 
if(!strstr($key, " attr")){ #if it's not an attribute 
if(array_key_exists("$key attr", $data)){ 
while(list($attr_name, $attr_value) = each($data["$key attr"])){ 
#echo "Found attribute $attribute_name with value $attribute_value<br>"; 
$attr_value = &htmlspecialchars($attr_value, ENT_QUOTES); 
$attributes .= " $attr_name=\"$attr_value\""; 
} 
} 
if(is_numeric($key)){ 
#echo "My current key ($key) is numeric. My parent key is '$prior_key'<br>"; 
$key = $prior_key; 
}else{ 
#you can't have numeric keys at two levels in a row, so this is ok 
#echo "Checking to see if a numeric key exists in data."; 
if(is_array($value) and array_key_exists(0, $value)){ 
# echo " It does! Calling myself as a result of a numeric array.<br>"; 
$numeric_array = true; 
$xml_serialized_string .= XML_serialize($value, $level, $key); 
} 
#echo "<br>"; 
} 
if(!$numeric_array){ 
$xml_serialized_string .= str_repeat("\t", $level) . "<$key$attributes>"; 
if(is_array($value)){ 
$xml_serialized_string .= "\r\n" . XML_serialize($value, $level+1); 
}else{ 
$inline = true; 
$xml_serialized_string .= htmlspecialchars($value); 
} 
$xml_serialized_string .= (!$inline ? str_repeat("\t", $level) : "") . "</$key>\r\n"; 
} 
}else{ 
#echo "Skipping attribute record for key $key<bR>"; 
} 
} 
if($level == 0){ 
$xml_serialized_string = "<?xml version=\"1.0\" ?>\r\n" . $xml_serialized_string; 
return $xml_serialized_string; 
}else{ 
return $xml_serialized_string; 
} 
} 
class XML { 
var $parser; #a reference to the XML parser 
var $document; #the entire XML structure built up so far 
var $current; #a pointer to the current item - what is this 
var $parent; #a pointer to the current parent - the parent will be an array 
var $parents; #an array of the most recent parent at each level 
var $last_opened_tag; 
function XML($data=null){ 
$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, "open", "close"); 
xml_set_character_data_handler($this->parser, "data"); 
# register_shutdown_function(array($this, 'destruct')); 
} 
function destruct(){ 
xml_parser_free($this->parser); 
} 
function parse($data){ 
$this->document = array(); 
$this->parent = $this->document; 
$this->parents = array(); 
$this->last_opened_tag = NULL; 
xml_parse($this->parser, $data); 
return $this->document; 
} 
function open($parser, $tag, $attributes){ 
#echo "Opening tag $tag<br>\n"; 
$this->data = ""; 
$this->last_opened_tag = $tag; #tag is a string 
if(array_key_exists($tag, $this->parent)){ 
#echo "There's already an instance of '$tag' at the current level ($level)<br>\n"; 
if(is_array($this->parent[$tag]) and array_key_exists(0, $this->parent[$tag])){ #if the keys are numeric 
#need to make sure they're numeric (account for attributes) 
$key = count_numeric_items($this->parent[$tag]); 
#echo "There are $key instances: the keys are numeric.<br>\n"; 
}else{ 
#echo "There is only one instance. Shifting everything around<br>\n"; 
$temp = $this->parent[$tag]; 
unset($this->parent[$tag]); 
$this->parent[$tag][0] = $temp; 
if(array_key_exists("$tag attr", $this->parent)){ 
#shift the attributes around too if they exist 
$temp = $this->parent["$tag attr"]; 
unset($this->parent["$tag attr"]); 
$this->parent[$tag]["0 attr"] = $temp; 
} 
$key = 1; 
} 
$this->parent = $this->parent[$tag]; 
}else{ 
$key = $tag; 
} 
if($attributes){ 
$this->parent["$key attr"] = $attributes; 
} 
$this->parent[$key] = array(); 
$this->parent = $this->parent[$key]; 
array_unshift($this->parents, $this->parent); 
} 
function data($parser, $data){ 
#echo "Data is '", htmlspecialchars($data), "'<br>\n"; 
if($this->last_opened_tag != NULL){ 
$this->data .= $data; 
} 
} 
function close($parser, $tag){ 
#echo "Close tag $tag<br>\n"; 
if($this->last_opened_tag == $tag){ 
$this->parent = $this->data; 
$this->last_opened_tag = NULL; 
} 
array_shift($this->parents); 
$this->parent = $this->parents[0]; 
} 
} 
function & XML_unserialize($xml){ 
$xml_parser = new XML(); 
$data = $xml_parser->parse($xml); 
$xml_parser->destruct(); 
return $data; 
} 
function & XMLRPC_parse($request){ 
if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){ 
XMLRPC_debug('XMLRPC_parse', "<p>Received the following raw request:</p>" . XMLRPC_show($request, 'print_r', true)); 
} 
$data = &XML_unserialize($request); 
if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){ 
XMLRPC_debug('XMLRPC_parse', "<p>Returning the following parsed request:</p>" . XMLRPC_show($data, 'print_r', true)); 
} 
return $data; 
} 
function & XMLRPC_prepare($data, $type = NULL){ 
if(is_array($data)){ 
$num_elements = count($data); 
if((array_key_exists(0, $data) or !$num_elements) and $type != 'struct'){ #it's an array 
if(!$num_elements){ #if the array is emptyempty 
$returnvalue = array('array' => array('data' => NULL)); 
}else{ 
$returnvalue['array']['data']['value'] = array(); 
$temp = $returnvalue['array']['data']['value']; 
$count = count_numeric_items($data); 
for($n=0; $n<$count; $n++){ 
$type = NULL; 
if(array_key_exists("$n type", $data)){ 
$type = $data["$n type"]; 
} 
$temp[$n] = XMLRPC_prepare($data[$n], $type); 
} 
} 
}else{ #it's a struct 
if(!$num_elements){ #if the struct is emptyempty 
$returnvalue = array('struct' => NULL); 
}else{ 
$returnvalue['struct']['member'] = array(); 
$temp = $returnvalue['struct']['member']; 
while(list($key, $value) = each($data)){ 
if(substr($key, -5) != ' type'){ #if it's not a type specifier 
$type = NULL; 
if(array_key_exists("$key type", $data)){ 
$type = $data["$key type"]; 
} 
$temp[] = array('name' => $key, 'value' => XMLRPC_prepare($value, $type)); 
} 
} 
} 
} 
}else{ #it's a scalar 
if(!$type){ 
if(is_int($data)){ 
$returnvalue['int'] = $data; 
return $returnvalue; 
}elseif(is_float($data)){ 
$returnvalue['double'] = $data; 
return $returnvalue; 
}elseif(is_bool($data)){ 
$returnvalue['boolean'] = ($data ? 1 : 0); 
return $returnvalue; 
}elseif(preg_match('/^\d{8}T\d{2}:\d{2}:\d{2}$/', $data, $matches)){ #it's a date 
$returnvalue['dateTime.iso8601'] = $data; 
return $returnvalue; 
}elseif(is_string($data)){ 
$returnvalue['string'] = htmlspecialchars($data); 
return $returnvalue; 
} 
}else{ 
$returnvalue[$type] = htmlspecialchars($data); 
} 
} 
return $returnvalue; 
} 
function & XMLRPC_adjustValue($current_node){ 
if(is_array($current_node)){ 
if(isset($current_node['array'])){ 
if(!is_array($current_node['array']['data'])){ 
#If there are no elements, return an emptyempty array 
return array(); 
}else{ 
#echo "Getting rid of array -> data -> value<br>\n"; 
$temp = $current_node['array']['data']['value']; 
if(is_array($temp) and array_key_exists(0, $temp)){ 
$count = count($temp); 
for($n=0;$n<$count;$n++){ 
$temp2[$n] = &XMLRPC_adjustValue($temp[$n]); 
} 
$temp = $temp2; 
}else{ 
$temp2 = &XMLRPC_adjustValue($temp); 
$temp = array($temp2); 
#I do the temp assignment because it avoids copying, 
# since I can put a reference in the array 
#PHP's reference model is a bit silly, and I can't just say: 
# $temp = array(&XMLRPC_adjustValue($temp)); 
} 
} 
}elseif(isset($current_node['struct'])){ 
if(!is_array($current_node['struct'])){ 
#If there are no members, return an emptyempty array 
return array(); 
}else{ 
#echo "Getting rid of struct -> member<br>\n"; 
$temp = $current_node['struct']['member']; 
if(is_array($temp) and array_key_exists(0, $temp)){ 
$count = count($temp); 
for($n=0;$n<$count;$n++){ 
#echo "Passing name {$temp[$n][name]}. Value is: " . show($temp[$n][value], var_dump, true) . "<br>\n"; 
$temp2[$temp[$n]['name']] = &XMLRPC_adjustValue($temp[$n]['value']); 
#echo "adjustValue(): After assigning, the value is " . show($temp2[$temp[$n]['name']], var_dump, true) . "<br>\n"; 
} 
}else{ 
#echo "Passing name $temp[name]<br>\n"; 
$temp2[$temp['name']] = &XMLRPC_adjustValue($temp['value']); 
} 
$temp = $temp2; 
} 
}else{ 
$types = array('string', 'int', 'i4', 'double', 'dateTime.iso8601', 'base64', 'boolean'); 
$fell_through = true; 
foreach($types as $type){ 
if(array_key_exists($type, $current_node)){ 
#echo "Getting rid of '$type'<br>\n"; 
$temp = $current_node[$type]; 
#echo "adjustValue(): The current node is set with a type of $type<br>\n"; 
$fell_through = false; 
break; 
} 
} 
if($fell_through){ 
$type = 'string'; 
#echo "Fell through! Type is $type<br>\n"; 
} 
switch ($type){ 
case 'int': case 'i4': $temp = (int)$temp; break; 
case 'string': $temp = (string)$temp; break; 
case 'double': $temp = (double)$temp; break; 
case 'boolean': $temp = (bool)$temp; break; 
} 
} 
}else{ 
$temp = (string)$current_node; 
} 
return $temp; 
} 
function XMLRPC_getParams($request){ 
if(!is_array($request['methodCall']['params'])){ 
#If there are no parameters, return an emptyempty array 
return array(); 
}else{ 
#echo "Getting rid of methodCall -> params -> param<br>\n"; 
$temp = $request['methodCall']['params']['param']; 
if(is_array($temp) and array_key_exists(0, $temp)){ 
$count = count($temp); 
for($n = 0; $n < $count; $n++){ 
#echo "Serializing parameter $n<br>"; 
$temp2[$n] = &XMLRPC_adjustValue($temp[$n]['value']); 
} 
}else{ 
$temp2[0] = &XMLRPC_adjustValue($temp['value']); 
} 
$temp = $temp2; 
return $temp; 
} 
} 
function XMLRPC_getMethodName($methodCall){ 
#returns the method name 
return $methodCall['methodCall']['methodName']; 
} 
function XMLRPC_request($site, $location, $methodName, $params = NULL, $user_agent = NULL){ 
$site = explode(':', $site); 
if(isset($site[1]) and is_numeric($site[1])){ 
$port = $site[1]; 
}else{ 
$port = 80; 
} 
$site = $site[0]; 
$data["methodCall"]["methodName"] = $methodName; 
$param_count = count($params); 
if(!$param_count){ 
$data["methodCall"]["params"] = NULL; 
}else{ 
for($n = 0; $n<$param_count; $n++){ 
$data["methodCall"]["params"]["param"][$n]["value"] = $params[$n]; 
} 
} 
$data = XML_serialize($data); 
if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){ 
XMLRPC_debug('XMLRPC_request', "<p>Received the following parameter list to send:</p>" . XMLRPC_show($params, 'print_r', true)); 
} 
$conn = fsockopen ($site, $port); #open the connection 
if(!$conn){ #if the connection was not opened successfully 
if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){ 
XMLRPC_debug('XMLRPC_request', "<p>Connection failed: Couldn't make the connection to $site.</p>"); 
} 
return array(false, array('faultCode'=>10532, 'faultString'=>"Connection failed: Couldn't make the connection to $site.")); 
}else{ 
$headers = 
"POST $location HTTP/1.0\r\n" . 
"Host: $site\r\n" . 
"Connection: close\r\n" . 
($user_agent ? "User-Agent: $user_agent\r\n" : '') . 
"Content-Type: text/xml\r\n" . 
"Content-Length: " . strlen($data) . "\r\n\r\n"; 
fputs($conn, "$headers"); 
fputs($conn, $data); 
if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){ 
XMLRPC_debug('XMLRPC_request', "<p>Sent the following request:</p>\n\n" . XMLRPC_show($headers . $data, 'print_r', true)); 
} 
#socket_set_blocking ($conn, false); 
$response = ""; 
while(!feof($conn)){ 
$response .= fgets($conn, 1024); 
} 
fclose($conn); 
#strip headers off of response 
$data = XML_unserialize(substr($response, strpos($response, "\r\n\r\n")+4)); 
if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){ 
XMLRPC_debug('XMLRPC_request', "<p>Received the following response:</p>\n\n" . XMLRPC_show($response, 'print_r', true) . "<p>Which was serialized into the following data:</p>\n\n" . XMLRPC_show($data, 'print_r', true)); 
} 
if(isset($data['methodResponse']['fault'])){ 
$return = array(false, XMLRPC_adjustValue($data['methodResponse']['fault']['value'])); 
if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){ 
XMLRPC_debug('XMLRPC_request', "<p>Returning:</p>\n\n" . XMLRPC_show($return, 'var_dump', true)); 
} 
return $return; 
}else{ 
$return = array(true, XMLRPC_adjustValue($data['methodResponse']['params']['param']['value'])); 
if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){ 
XMLRPC_debug('XMLRPC_request', "<p>Returning:</p>\n\n" . XMLRPC_show($return, 'var_dump', true)); 
} 
return $return; 
} 
} 
} 
function XMLRPC_response($return_value, $server = NULL){ 
$data["methodResponse"]["params"]["param"]["value"] = $return_value; 
$return = XML_serialize($data); 
if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){ 
XMLRPC_debug('XMLRPC_response', "<p>Received the following data to return:</p>\n\n" . XMLRPC_show($return_value, 'print_r', true)); 
} 
header("Connection: close"); 
header("Content-Length: " . strlen($return)); 
header("Content-Type: text/xml"); 
header("Date: " . date("r")); 
if($server){ 
header("Server: $server"); 
} 
if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){ 
XMLRPC_debug('XMLRPC_response', "<p>Sent the following response:</p>\n\n" . XMLRPC_show($return, 'print_r', true)); 
} 
echo $return; 
} 
function XMLRPC_error($faultCode, $faultString, $server = NULL){ 
$array["methodResponse"]["fault"]["value"]["struct"]["member"] = array(); 
$temp = $array["methodResponse"]["fault"]["value"]["struct"]["member"]; 
$temp[0]["name"] = "faultCode"; 
$temp[0]["value"]["int"] = $faultCode; 
$temp[1]["name"] = "faultString"; 
$temp[1]["value"]["string"] = $faultString; 
$return = XML_serialize($array); 
header("Connection: close"); 
header("Content-Length: " . strlen($return)); 
header("Content-Type: text/xml"); 
header("Date: " . date("r")); 
if($server){ 
header("Server: $server"); 
} 
if(defined('XMLRPC_DEBUG') and XMLRPC_DEBUG){ 
XMLRPC_debug('XMLRPC_error', "<p>Sent the following error response:</p>\n\n" . XMLRPC_show($return, 'print_r', true)); 
} 
echo $return; 
} 
function XMLRPC_convert_timestamp_to_iso8601($timestamp){ 
#takes a unix timestamp and converts it to iso8601 required by XMLRPC 
#an example iso8601 datetime is "20010822T03:14:33" 
return date("Ymd\TH:i:s", $timestamp); 
} 
function XMLRPC_convert_iso8601_to_timestamp($iso8601){ 
return strtotime($iso8601); 
} 
function count_numeric_items($array){ 
return is_array($array) ? count(array_filter(array_keys($array), 'is_numeric')) : 0; 
} 
function XMLRPC_debug($function_name, $debug_message){ 
$GLOBALS['XMLRPC_DEBUG_INFO'][] = array($function_name, $debug_message); 
} 
function XMLRPC_debug_print(){ 
if($GLOBALS['XMLRPC_DEBUG_INFO']){ 
echo "<table border=\"1\" width=\"100%\">\n"; 
foreach($GLOBALS['XMLRPC_DEBUG_INFO'] as $debug){ 
echo "<tr><th style=\"vertical-align: top\">$debug[0]</th><td>$debug[1]</td></tr>\n"; 
} 
echo "</table>\n"; 
unset($GLOBALS['XMLRPC_DEBUG_INFO']); 
}else{ 
echo "<p>No debugging information available yet.</p>"; 
} 
} 
function XMLRPC_show($data, $func = "print_r", $return_str = false){ 
ob_start(); 
$func($data); 
$output = ob_get_contents(); 
ob_end_clean(); 
if($return_str){ 
return "<pre>" . htmlspecialchars($output) . "</pre>\n"; 
}else{ 
echo "<pre>", htmlspecialchars($output), "</pre>\n"; 
} 
} 
?>

服务端程序例子,server.php
<? 
include 'xml-rpc.inc.php'; 
//定义可被远程调用的方法 
$xmlrpc_methods=array(); 
$xmlrpc_methods['insertRecords']='insertRecords'; //获得用户传入的方法名和参数 
$xmlrpc_request = XMLRPC_parse($HTTP_RAW_POST_DATA); 
$methodName = XMLRPC_getMethodName($xmlrpc_request); 
$params = XMLRPC_getParams($xmlrpc_request); 
if (!isset($xmlrpc_methods[$methodName])){ 
XMLRPC_error('1',"你所调用的方法不存在"); 
}else { 
$xmlrpc_methods[$methodName]($params); 
} 
function insertRecords($params){ 
if (emptyempty($params)){ 
XMLRPC_error('2',"参数出错"); 
} 
XMLRPC_response(XMLRPC_prepare('http://www.emtit.com')); 
} 
?>

PHP客户端调用服务端方法例子
<?php 
include_once 'xml-rpc.inc'; 
$params=array(2,3); 
$result=XMLRPC_request("127.0.0.1","/services/server.php","insertRecords",$params);//服务端文件放在services文件夹下 
print_r($result); 
?>

结果会显示www.emtiit.com
PHP 相关文章推荐
mysql_fetch_assoc和mysql_fetch_row的功能加起来就是mysql_fetch_array
Jan 15 PHP
php绝对路径与相对路径之间关系的的分析
Mar 03 PHP
很让人受教的 提高php代码质量36计
Sep 05 PHP
php中$美元符号与Zen Coding冲突问题解决方法分享
May 28 PHP
PHP5.5和之前的版本empty函数的不同之处
Jun 13 PHP
ThinkPHP中的常用查询语言汇总
Aug 22 PHP
PHP图像处理之使用imagecolorallocate()函数设置颜色例子
Nov 19 PHP
实例讲解如何在PHP的Yii框架中进行错误和异常处理
Mar 17 PHP
PHP中常用的数组操作方法笔记整理
May 16 PHP
AES加解密在php接口请求过程中的应用示例
Oct 26 PHP
PHP时间戳和日期相互转换操作实例小结
Dec 18 PHP
php 文件上传至OSS及删除远程阿里云OSS文件
Jul 04 PHP
php 设计模式之 工厂模式
Dec 19 #PHP
php 设计模式之 单例模式
Dec 19 #PHP
PHP 采集程序 常用函数
Dec 18 #PHP
php IP及IP段进行访问限制的代码
Dec 17 #PHP
php mssql 数据库分页SQL语句
Dec 16 #PHP
linux下 C语言对 php 扩展
Dec 14 #PHP
php 文件状态缓存带来的问题
Dec 14 #PHP
You might like
编译PHP报错configure error Cannot find libmysqlclient under usr的解决方法
2014/06/27 PHP
thinkphp实现图片上传功能
2016/01/13 PHP
jQuery的一些注意
2006/12/06 Javascript
使用Jquery Aajx访问WCF服务(GET、POST、PUT、DELETE)
2012/03/16 Javascript
用js编写的简单的计算器代码程序
2015/08/04 Javascript
三种AngularJS中获取数据源的方式
2016/02/02 Javascript
深入剖析JavaScript面向对象编程
2016/07/12 Javascript
微信小程序 wx:key详细介绍
2016/10/28 Javascript
bootstrap flask登录页面编写实例
2016/11/01 Javascript
jQuery Dialog 打开时自动聚焦的解决方法(两种方法)
2016/11/24 Javascript
JS对象深度克隆实例分析
2017/03/16 Javascript
详解nodejs模板引擎制作
2017/06/14 NodeJs
详解vue组件开发脚手架
2018/06/15 Javascript
vue实现点击关注后及时更新列表功能
2018/06/26 Javascript
jQuery中$原理实例分析
2018/08/13 jQuery
详解wepy开发小程序踩过的坑(小结)
2019/05/22 Javascript
Vue-cli3.X使用px2 rem遇到的问题及解决方法
2019/08/08 Javascript
详解element-ui 表单校验 Rules 配置 常用黑科技
2020/07/11 Javascript
[04:37]DOTA2英雄梦之声Vol20发条
2014/06/20 DOTA
[06:25]第二届DOTA2亚洲邀请赛主赛事第二天比赛集锦.mp4
2017/04/03 DOTA
[49:31]TFT vs Mski Supermajor小组赛C组 BO3 第一场 6.3
2018/06/04 DOTA
python开发之tkinter实现图形随鼠标移动的方法
2015/11/11 Python
MySQL适配器PyMySQL详解
2017/09/20 Python
python利用有道翻译实现&quot;语言翻译器&quot;的功能实例
2017/11/14 Python
django-crontab实现服务端的定时任务的示例代码
2020/02/17 Python
突袭HTML5之Javascript API扩展2—地理信息服务及地理位置API学习
2013/01/31 HTML / CSS
Conforama瑞士:家具、厨房、电器、装饰
2020/09/06 全球购物
怎么写好自荐信
2013/10/30 职场文书
简历里的自我评价
2014/01/31 职场文书
服务理念标语
2014/06/18 职场文书
工作目标责任书
2014/07/23 职场文书
市委召开党的群众路线教育实践活动总结大会报告
2014/10/21 职场文书
党员群众路线整改措施及今后努力方向
2014/10/28 职场文书
小学庆六一主持词
2015/06/30 职场文书
Python Matplotlib绘制条形图的全过程
2021/10/24 Python
MySql数据库触发器使用教程
2022/06/01 MySQL