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 相关文章推荐
一个好用的分页函数
Nov 16 PHP
浅析PHP水印技术
Feb 14 PHP
手把手教你使用DedeCms V3的在线采集图文教程
Apr 03 PHP
php中$this-&amp;gt;含义分析
Nov 29 PHP
PHP 图片文件上传实现代码
Dec 29 PHP
php学习之运算符相关概念
Jun 09 PHP
浅析PHP中Collection 类的设计
Jun 21 PHP
php CI框架插入一条或多条sql记录示例
Jul 29 PHP
PHP中几个可以提高运行效率的代码写法、技巧分享
Aug 21 PHP
php创建和删除目录函数介绍和递归删除目录函数分享
Nov 18 PHP
php中引用&amp;的用法分析【变量引用,函数引用,对象引用】
Dec 12 PHP
php生成复杂验证码(倾斜,正弦干扰线,黏贴,旋转)
Mar 12 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访问Google Search API的方法
2015/03/05 PHP
Laravel 5框架学习之Eloquent (laravel 的ORM)
2015/04/08 PHP
win10下 php安装seaslog扩展的详细步骤
2020/12/04 PHP
使用JQuery和s3captche实现一个水果名字的验证
2009/08/14 Javascript
火狐4、谷歌12不支持Jquery Validator的解决方法分享
2011/06/20 Javascript
js特效,页面下雪的小例子
2013/06/17 Javascript
js 动态加载事件的几种方法总结
2013/12/25 Javascript
jquery的父子兄弟节点查找示例代码
2014/03/03 Javascript
js创建一个input数组并绑定click事件的方法
2014/06/12 Javascript
nodejs教程之入门
2014/11/21 NodeJs
使用jquery实现鼠标滑过弹出更多相关信息层附源码下载
2015/11/23 Javascript
JavaScript深度复制(deep clone)的实现方法
2016/02/19 Javascript
基于Layer+jQuery的自定义弹框
2020/05/26 Javascript
H5实现中奖记录逐行滚动切换效果
2017/03/13 Javascript
Sublime Text新建.vue模板并高亮(图文教程)
2017/10/26 Javascript
解决npm安装Electron缓慢网络超时导致失败的问题
2018/02/06 Javascript
浅析Vue项目中使用keep-Alive步骤
2018/07/27 Javascript
javascript贪吃蛇游戏设计与实现
2020/09/17 Javascript
python中xrange用法分析
2015/04/15 Python
Python实现递归遍历文件夹并删除文件
2016/04/18 Python
Apache如何部署django项目
2017/05/21 Python
Python 判断是否为质数或素数的实例
2017/10/30 Python
python点击鼠标获取坐标(Graphics)
2019/08/10 Python
flask 使用 flask_apscheduler 做定时循环任务的实现
2019/12/10 Python
Python sqlite3查询操作过程解析
2020/02/20 Python
python之生成多层json结构的实现
2020/02/27 Python
django admin管理工具自定义时间区间筛选器DateRangeFilter介绍
2020/05/19 Python
HTML5 客户端数据库简易使用:IndexedDB
2019/12/19 HTML / CSS
哈利波特商店:Harry Potter Shop
2018/11/30 全球购物
Nº21官方在线商店:numeroventuno.com
2019/09/26 全球购物
土木工程应届生自荐信
2013/09/24 职场文书
公证书样本
2014/04/10 职场文书
村干部群众路线整改措施思想汇报
2014/10/12 职场文书
导游词怎么写
2015/02/04 职场文书
任命书标准格式
2015/03/02 职场文书
2016年学校禁毒宣传活动工作总结
2016/04/05 职场文书