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>"; }
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();
function open($parser, $tag, $attributes){ #echo "Opening tag $tag<br>
"; $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>
"; 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>
"; }else{ #echo "There is only one instance. Shifting everything around<br>
"; $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; }
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_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>
"; $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>
"; $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>
"; $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>
"; } }else{ #echo "Passing name $temp[name]<br>
"; $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>
"; $temp = $current_node[$type]; #echo "adjustValue(): The current node is set with a type of $type<br>
"; $fell_through = false; break; } } if($fell_through){ $type = "string"; #echo "Fell through! Type is $type<br>
"; } 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>
"; $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"]; }
if(defined("XMLRPC_DEBUG") and XMLRPC_DEBUG){ XMLRPC_debug("XMLRPC_response", "<p>Received the following data to return:</p>
" . XMLRPC_show($return_value, "print_r", true)); }
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("YmdTH: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%">
"; foreach($GLOBALS["XMLRPC_DEBUG_INFO"] as $debug){ echo "<tr><th style="vertical-align: top">$debug[0]</th><td>$debug[1]</td></tr>
"; } echo "</table>
"; unset($GLOBALS["XMLRPC_DEBUG_INFO"]); }else{ echo "<p>No debugging information available yet.</p>"; } }