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 相关文章推荐
利用php来自动调用不同服务器上的flash
Oct 09 PHP
PHP stristr() 函数(不区分大小写的字符串查找)
Jun 03 PHP
PHP中usort在值相同时改变原始位置问题的解决方法
Nov 27 PHP
如何用php获取程序执行的时间
Jun 09 PHP
php实现查询百度google收录情况(示例代码)
Aug 02 PHP
Symfony页面的基本创建实例详解
Jan 26 PHP
简单谈谈php延迟静态绑定
Jan 26 PHP
PHP微信开发之查询微信精选文章
Jun 23 PHP
thinkphp在php7环境下提示Cannot use ‘String’ as class name as it is reserved的解决方法
Sep 30 PHP
php异常处理捕获错误整理
Sep 23 PHP
PHP实现二维数组(或多维数组)转换成一维数组的常见方法总结
Dec 04 PHP
PHP基于array_unique实现二维数组去重
Jul 14 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+mysql写的留言本
2006/10/09 PHP
php修改NetBeans默认字体的大小
2013/07/02 PHP
php查询mssql出现乱码的解决方法
2014/12/29 PHP
PHP如何搭建百度Ueditor富文本编辑器
2018/09/21 PHP
JS获取IUSR_机器名和IWAM_机器名帐号的密码
2006/12/06 Javascript
15款优秀的jQuery导航菜单插件分享
2011/07/19 Javascript
JS 获取滚动条高度示例代码
2013/10/24 Javascript
jquery解析xml字符串示例分享
2014/03/25 Javascript
jQuery遍历对象、数组、集合实例
2014/11/08 Javascript
javascript字符串与数组转换汇总
2015/05/26 Javascript
JS 获取HTML标签内的子节点的方法
2016/09/21 Javascript
KVM虚拟化技术之使用Qemu-kvm创建和管理虚拟机的方法
2016/10/05 Javascript
javascript中递归的两种写法
2017/01/17 Javascript
详解在vue-cli中使用路由
2017/09/25 Javascript
基于滚动条位置判断的简单实例
2017/12/14 Javascript
Nodejs连接mysql并实现增、删、改、查操作的方法详解
2018/01/04 NodeJs
vue的全局变量和全局拦截请求器的示例代码
2018/09/13 Javascript
element-ui中el-upload多文件一次性上传的实现
2020/12/02 Javascript
wxPython窗口的继承机制实例分析
2014/09/28 Python
Python的Flask框架中实现分页功能的教程
2015/04/20 Python
详解Python的单元测试
2015/04/28 Python
Python数据类型学习笔记
2016/01/13 Python
python基于http下载视频或音频
2018/06/20 Python
Python pip安装第三方库实现过程解析
2020/07/09 Python
美国摄影爱好者购物网站:Focus Camera
2016/10/21 全球购物
大学生如何写自荐信
2014/01/08 职场文书
小学班主任寄语大全
2014/04/04 职场文书
支行行长竞聘演讲稿
2014/05/15 职场文书
教师敬业奉献模范事迹材料
2014/05/18 职场文书
平安家庭示范户事迹
2014/06/02 职场文书
计算机系统管理员求职信
2014/06/20 职场文书
报到证办理个人委托书
2014/10/06 职场文书
新年寄语2016
2015/08/17 职场文书
Golang并发操作中常见的读写锁详析
2021/08/30 Golang
python字符串拼接.join()和拆分.split()详解
2021/11/23 Python
MySql数据库 查询时间序列间隔
2022/05/11 MySQL