인터넷에 있는 XML-RPC 라이브러리는 소규모 외부 통신 인터페이스를 개발하는 데 매우 유용합니다. 이 코드를 xml-rpc.inc.php
<?php
로 저장하세요.
/*
인터넷에 있는 XML-RPC 라이브러리는 소규모 외부 통신 인터페이스를 개발하는 데 매우 유용합니다.
*/
함수 & XML_serialize($data, $level = 0, $prior_key = NULL){
#해시를 가정하고 키는 변수 이름입니다.
$xml_serialized_string = "";
while(list($key, $value) = 각각($data)){
$인라인 = 거짓;
$numeric_array = 거짓;
$속성 = "";
#echo "현재 키는 '$key'이며 이전 키 '$prior_key'<br>로 호출되었습니다.";
if(!strstr($key, " attr")){ #속성이 아닌 경우
if(array_key_exists("$key attr", $data)){
while(list($attr_name, $attr_value) = 각각($data["$key attr"])){
#echo "값이 $attribute_value인 $attribute_name 속성을 찾았습니다<br>";
$attr_value = &htmlspecialchars($attr_value, ENT_QUOTES);
$attributes .= " $attr_name="$attr_value"";
}
}
if(is_numeric($key)){
#echo "내 현재 키($key)는 숫자입니다. 내 상위 키는 '$prior_key'입니다.<br>";
$key = $prior_key;
}또 다른{
#연속해서 두 단계에 숫자 키를 사용할 수 없으므로 괜찮습니다.
#echo "데이터에 숫자 키가 있는지 확인하는 중입니다.";
if(is_array($value) 및 array_key_exists(0, $value)){
# echo "그렇습니다! 숫자 배열의 결과로 나 자신을 호출합니다.<br>";
$numeric_array = 참;
$xml_serialized_string .= XML_serialize($value, $level, $key);
}
#에코 "<br>";
}
if(!$numeric_array){
$xml_serialized_string .= str_repeat("t", $level) "<$key$attributes>";
if(is_array($값)){
$xml_serialized_string .= "rn" . XML_serialize($value, $level+1);
}또 다른{
$인라인 = 사실;
$xml_serialized_string .= htmlspecialchars($value);
}
$xml_serialized_string .= (!$inline ? str_repeat("t", $level) : "") "</$key>rn";
}
}또 다른{
#echo "$key<bR> 키에 대한 속성 레코드를 건너뛰는 중";
}
}
if($레벨 == 0){
$xml_serialized_string = "<?xml 버전="1.0" ?>rn" .
$xml_serialized_string을 반환합니다.
}또 다른{
$xml_serialized_string을 반환합니다.
}
}
클래스 XML {
var $parser #a XML 파서에 대한 참조
var $document; #지금까지 구축된 전체 XML 구조
var $current; #현재 항목에 대한 포인터 - 이것은 무엇입니까?
var $parent; # 현재 부모에 대한 포인터 - 부모는 배열이 됩니다.
var $parents; #각 레벨의 가장 최근 부모 배열
var $last_opened_tag;
함수 XML($data=null){
$this->parser = xml_parser_create();
xml_parser_set_option ($this->파서, XML_OPTION_CASE_FOLDING, 0);
xml_set_object($this->파서, $this);
xml_set_element_handler($this->parser, "open", "close");
xml_set_character_data_handler($this->parser, "데이터");
# Register_shutdown_function(array($this, 'destruct'));
}
함수 파괴(){
xml_parser_free($this->파서);
}
함수 구문 분석($data){
$this->document = 배열();
$this->부모 = $this->문서;
$this->부모 = 배열();
$this->last_opened_tag = NULL;
xml_parse($this->파서, $data);
$this->document를 반환합니다.
}
함수 열기($parser, $tag, $attributes){
#echo "$tag 열기 태그<br>n";
$this->data = "";
$this->last_opened_tag = $tag는 문자열입니다.
if(array_key_exists($tag, $this->parent)){
#echo "현재 레벨($level)에 이미 '$tag' 인스턴스가 있습니다.<br>n";
if(is_array($this->parent[$tag]) and array_key_exists(0, $this->parent[$tag])){ # 키가 숫자인 경우
# 숫자인지 확인해야 합니다(속성을 고려).
$key = count_numeric_items($this->parent[$tag]);
#echo "$key 인스턴스가 있습니다. 키는 숫자입니다.<br>n";
}또 다른{
#echo "단 하나의 인스턴스만 있습니다. 모든 것을 이동합니다.<br>n";
$temp = $this->부모[$tag];
unset($this->parent[$tag]);
$this->parent[$tag][0] = $temp;
if(array_key_exists("$tag attr", $this->parent)){
#속성이 존재하는 경우 속성도 이동합니다.
$temp = $this->parent["$tag attr"];
unset($this->parent["$tag attr"]);
$this->parent[$tag]["0 attr"] = $temp;
}
$키 = 1;
}
$this->부모 = $this->부모[$tag];
}또 다른{
$키 = $태그;
}
if($속성){
$this->parent["$key attr"] = $속성;
}
$this->parent[$key] = 배열();
$this->부모 = $this->부모[$key];
array_unshift($this->부모, $this->부모);
}
함수 데이터($parser, $data){
#echo "데이터는 '", htmlspecialchars($data), "'<br>n";
if($this->last_opened_tag != NULL){
$this->data .= $data;
}
}
함수 닫기($parser, $tag){
#echo "$tag 태그 닫기<br>n";
if($this->last_opened_tag == $tag){
$this->부모 = $this->데이터;
$this->last_opened_tag = NULL;
}
array_shift($this->부모);
$this->부모 = $this->부모[0];
}
}
함수 & XML_unserialize($xml){
$xml_parser = 새로운 XML();
$data = $xml_parser->parse($xml);
$xml_parser->destruct();
$data를 반환합니다.
}
함수 & XMLRPC_parse($request){
if(정의('XMLRPC_DEBUG') 및 XMLRPC_DEBUG){
XMLRPC_debug('XMLRPC_parse', "<p>다음 원시 요청을 받았습니다:</p>" . XMLRPC_show($request, 'print_r', true));
}
$data = &XML_unserialize($request);
if(정의('XMLRPC_DEBUG') 및 XMLRPC_DEBUG){
XMLRPC_debug('XMLRPC_parse', "<p>다음 구문 분석된 요청 반환:</p>" . XMLRPC_show($data, 'print_r', true));
}
$data를 반환합니다.
}
함수 & XMLRPC_prepare($data, $type = NULL){
if(is_array($data)){
$num_elements = 개수($data);
if((array_key_exists(0, $data) 또는 !$num_elements) and $type != 'struct'){ # 배열입니다.
if(!$num_elements){ #배열이 비어 있는 경우empty
$returnvalue = array('배열' => array('데이터' => NULL));
}또 다른{
$returnvalue['배열']['데이터']['값'] = 배열();
$temp = $returnvalue['배열']['데이터']['값'];
$count = count_numeric_items($data);
for($n=0; $n<$count; $n++){
$유형 = NULL;
if(array_key_exists("$n 유형", $data)){
$type = $data["$n 유형"];
}
$temp[$n] = XMLRPC_prepare($data[$n], $type);
}
}
}else{ #구조체입니다
if(!$num_elements){ # 구조체가 비어 있는 경우empty
$returnvalue = array('struct' => NULL);
}또 다른{
$returnvalue['struct']['member'] = 배열();
$temp = $returnvalue['struct']['member'];
while(list($key, $value) = 각각($data)){
if(substr($key, -5) != ' type'){ # 유형 지정자가 아닌 경우
$유형 = NULL;
if(array_key_exists("$key type", $data)){
$type = $data["$key 유형"];
}
$temp[] = array('name' => $key, 'value' => XMLRPC_prepare($value, $type));
}
}
}
}
}else{ #스칼라입니다
if(!$유형){
if(is_int($data)){
$returnvalue['int'] = $data;
$returnvalue를 반환합니다.
}elseif(is_float($data)){
$returnvalue['double'] = $data;
$returnvalue를 반환합니다.
}elseif(is_bool($data)){
$returnvalue['boolean'] = ($data ? 1 : 0);
$returnvalue를 반환합니다.
}elseif(preg_match('/^d{8}Td{2}:d{2}:d{2}$/', $data, $matches)){ #날짜입니다
$returnvalue['dateTime.iso8601'] = $data;
$returnvalue를 반환합니다.
}elseif(is_string($data)){
$returnvalue['string'] = htmlspecialchars($data);
$returnvalue를 반환합니다.
}
}또 다른{
$returnvalue[$type] = htmlspecialchars($data);
}
}
$returnvalue를 반환합니다.
}
함수 & XMLRPC_adjustValue($current_node){
if(is_array($current_node)){
if(isset($current_node['배열'])){
if(!is_array($current_node['array']['data'])){
#요소가 없으면 빈 배열을 반환합니다.
반환 배열();
}또 다른{
#echo "배열 제거 -> 데이터 -> 값<br>n";
$temp = $current_node['배열']['데이터']['값'];
if(is_array($temp) 및 array_key_exists(0, $temp)){
$count = 개수($temp);
for($n=0;$n<$count;$n++){
$temp2[$n] = &XMLRPC_adjustValue($temp[$n]);
}
$임시 = $임시2;
}또 다른{
$temp2 = &XMLRPC_adjustValue($temp);
$temp = 배열($temp2);
#복사를 피하기 때문에 임시 과제를 하고,
# 배열에 참조를 넣을 수 있기 때문에
#PHP의 참조 모델은 약간 어리석기 때문에 다음과 같이 말할 수는 없습니다.
# $temp = array(&XMLRPC_adjustValue($temp));
}
}
}elseif(isset($current_node['struct'])){
if(!is_array($current_node['struct'])){
#멤버가 없으면 빈 배열을 반환합니다.
반환 배열();
}또 다른{
#echo "구조체 -> 멤버 제거<br>n";
$temp = $current_node['struct']['member'];
if(is_array($temp) 및 array_key_exists(0, $temp)){
$count = 개수($temp);
for($n=0;$n<$count;$n++){
#echo "이름 {$temp[$n][name]}을 전달합니다. 값은 다음과 같습니다. " . show($temp[$n][value], var_dump, true) "<br>n";
$temp2[$temp[$n]['name']] = &XMLRPC_adjustValue($temp[$n]['value']);
#echo "adjustValue(): 할당 후 값은 " 입니다. show($temp[$n]['name']], var_dump, true) "<br>n";
}
}또 다른{
#echo "전달 이름 $temp[name]<br>n";
$temp2[$temp['name']] = &XMLRPC_adjustValue($temp['value']);
}
$임시 = $임시2;
}
}또 다른{
$types = array('string', 'int', 'i4', 'double', 'dateTime.iso8601', 'base64', 'boolean');
$fell_through = 사실;
foreach($types를 $type으로){
if(array_key_exists($type, $current_node)){
#echo "'$type' 제거<br>n";
$temp = $current_node[$type];
#echo "adjustValue(): 현재 노드는 $type<br>n 유형으로 설정됩니다.";
$fell_through = 거짓;
부서지다;
}
}
if($fell_through){
$유형 = '문자열';
#echo "넘어갔습니다! 유형은 $type입니다<br>n";
}
스위치($type){
케이스 'int': 케이스 'i4': $temp = (int)$temp break;
케이스 '문자열': $temp = (string)$temp break;
케이스 '더블': $temp = (double)$temp break;
케이스 '부울': $temp = (bool)$temp break;
}
}
}또 다른{
$temp = (문자열)$current_node;
}
$temp를 반환합니다;
}
함수 XMLRPC_getParams($request){
if(!is_array($request['methodCall']['params'])){
#매개변수가 없으면 빈 배열을 반환합니다.
반환 배열();
}또 다른{
#echo "methodCall 제거 -> params -> param<br>n";
$temp = $request['methodCall']['params']['param'];
if(is_array($temp) 및 array_key_exists(0, $temp)){
$count = 개수($temp);
for($n = 0; $n < $count; $n++){
#echo "매개변수 $n<br> 직렬화 중";
$temp2[$n] = &XMLRPC_adjustValue($temp[$n]['값']);
}
}또 다른{
$temp2[0] = &XMLRPC_adjustValue($temp['value']);
}
$임시 = $임시2;
$temp를 반환합니다;
}
}
함수 XMLRPC_getMethodName($methodCall){
#메소드 이름을 반환합니다.
return $methodCall['methodCall']['methodName'];
}
함수 XMLRPC_request($site, $location, $methodName, $params = NULL, $user_agent = NULL){
$site = 폭발(':', $site);
if(isset($site[1]) 및 is_numeric($site[1])){
$port = $site[1];
}또 다른{
$ 포트 = 80;
}
$사이트 = $사이트[0];
$data["methodCall"]["methodName"] = $methodName;
$param_count = 개수($params);
if(!$param_count){
$data["methodCall"]["params"] = NULL;
}또 다른{
for($n = 0; $n<$param_count; $n++){
$data["methodCall"]["params"]["param"][$n]["value"] = $params[$n];
}
}
$data = XML_serialize($data);
if(정의('XMLRPC_DEBUG') 및 XMLRPC_DEBUG){
XMLRPC_debug('XMLRPC_request', "<p>전송할 다음 매개변수 목록을 받았습니다:</p>" . XMLRPC_show($params, 'print_r', true));
}
$conn = fsockopen ($site, $port) #연결을 엽니다.
if(!$conn){ # 연결이 성공적으로 열리지 않은 경우
if(정의('XMLRPC_DEBUG') 및 XMLRPC_DEBUG){
XMLRPC_debug('XMLRPC_request', "<p>연결 실패: $site에 연결할 수 없습니다.</p>");
}
return array(false, array('faultCode'=>10532, 'faultString'=>"연결 실패: $site에 연결할 수 없습니다."));
}또 다른{
$헤더 =
"POST $location HTTP/1.0rn" .
"호스트: $sitern" .
"연결: 닫기rn" .
($user_agent ? "사용자 에이전트: $user_agentrn" : '') .
"콘텐츠 유형: text/xmlrn" .
"콘텐츠 길이: " . strlen($data) . "rnrn";
fputs($conn, "$headers");
fputs($conn, $data);
if(정의('XMLRPC_DEBUG') 및 XMLRPC_DEBUG){
XMLRPC_debug('XMLRPC_request', "<p>다음 요청을 보냈습니다:</p>nn" . XMLRPC_show($headers . $data, 'print_r', true));
}
#socket_set_blocking($conn, false);
$응답 = "";
동안(!feof($conn)){
$response .= fgets($conn, 1024);
}
fclose($conn);
#응답에서 헤더 제거
$data = XML_unserialize(substr($response, strpos($response, "rnrn")+4));
if(정의('XMLRPC_DEBUG') 및 XMLRPC_DEBUG){
XMLRPC_debug('XMLRPC_request', "<p>다음 응답을 받았습니다:</p>nn" . XMLRPC_show($response, 'print_r', true) . "<p>다음 데이터로 직렬화되었습니다:< /p>nn" . XMLRPC_show($data, 'print_r', true));
}
if(isset($data['methodResponse']['fault'])){
$return = array(false, XMLRPC_adjustValue($data['methodResponse']['fault']['value']));
if(정의('XMLRPC_DEBUG') 및 XMLRPC_DEBUG){
XMLRPC_debug('XMLRPC_request', "<p>반환:</p>nn" . XMLRPC_show($return, 'var_dump', true));
}
$반환;
}또 다른{
$return = array(true, XMLRPC_adjustValue($data['methodResponse']['params']['param']['value']));
if(정의('XMLRPC_DEBUG') 및 XMLRPC_DEBUG){
XMLRPC_debug('XMLRPC_request', "<p>반환:</p>nn" . XMLRPC_show($return, 'var_dump', true));
}
$반환;
}
}
}
함수 XMLRPC_response($return_value, $server = NULL){
$data["methodResponse"]["params"]["param"]["value"] = $return_value;
$return = XML_serialize($data);
if(정의('XMLRPC_DEBUG') 및 XMLRPC_DEBUG){
XMLRPC_debug('XMLRPC_response', "<p>반환할 다음 데이터를 받았습니다:</p>nn" . XMLRPC_show($return_value, 'print_r', true));
}
header("연결: 종료");
header("콘텐츠 길이: " . strlen($return));
header("콘텐츠 유형: 텍스트/xml");
header("날짜: " . date("r"));
if($서버){
header("서버: $server");
}
if(정의('XMLRPC_DEBUG') 및 XMLRPC_DEBUG){
XMLRPC_debug('XMLRPC_response', "<p>다음 응답을 보냈습니다:</p>nn" . XMLRPC_show($return, 'print_r', true));
}
에코 $return;
}
함수 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("연결: 종료");
header("콘텐츠 길이: " . strlen($return));
header("콘텐츠 유형: 텍스트/xml");
header("날짜: " . date("r"));
if($서버){
header("서버: $server");
}
if(정의('XMLRPC_DEBUG') 및 XMLRPC_DEBUG){
XMLRPC_debug('XMLRPC_error', "<p>다음 오류 응답을 보냈습니다:</p>nn" . XMLRPC_show($return, 'print_r', true));
}
에코 $return;
}
함수 XMLRPC_convert_timestamp_to_iso8601($timestamp){
#Unix 타임스탬프를 가져와서 XMLRPC에 필요한 iso8601로 변환합니다.
#iso8601 날짜/시간의 예는 "20010822T03:14:33"입니다.
반환 날짜("YmdTH:i:s", $timestamp);
}
함수 XMLRPC_convert_iso8601_to_timestamp($iso8601){
strtotime($iso8601)을 반환합니다.
}
함수 count_numeric_items($array){
return is_array($array) ? count(array_filter(array_keys($array), 'is_numeric')) : 0;
}
함수 XMLRPC_debug($function_name, $debug_message){
$GLOBALS['XMLRPC_DEBUG_INFO'][] = 배열($function_name, $debug_message);
}
함수 XMLRPC_debug_print(){
if($GLOBALS['XMLRPC_DEBUG_INFO']){
echo "<테이블 테두리="1" 너비="100%">n";
foreach($GLOBALS['XMLRPC_DEBUG_INFO'] $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']);
}또 다른{
echo "<p>아직 디버깅 정보가 없습니다.</p>";
}
}
함수 XMLRPC_show($data, $func = "print_r", $return_str = false){
ob_start();
$func($data);
$output = ob_get_contents();
ob_end_clean();
if($return_str){
"<pre>" 를 반환합니다. htmlspecialchars($output) "</pre>n";
}또 다른{
echo "<pre>", htmlspecialchars($output), "</pre>n";
}
}
?>
서버 프로그램 예, server.php
<?
'xml-rpc.inc.php'를 포함합니다;
//원격으로 호출할 수 있는 메소드 정의
$xmlrpc_methods=배열();
$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',"호출한 메소드가 존재하지 않습니다.");
}또 다른 {
$xmlrpc_methods[$methodName]($params);
}
함수 insertRecords($params){
if (비어 있음($params)){
XMLRPC_error('2',"매개변수 오류");
}
XMLRPC_response(XMLRPC_prepare('http://www.emtit.com'));
}
?>
서버 메소드를 호출하는 PHP 클라이언트의 예
<?php
include_once 'xml-rpc.inc';
$params=배열(2,3);
$result=XMLRPC_request("127.0.0.1","/services/server.php","insertRecords",$params);//서버 파일은 services 폴더에 배치됩니다.
print_r($결과);
?>