<?php
//***************xml 與 array 之間的轉換處理一***********************/
function xml2array(&$xml, $isnormal = FALSE) {
$xml_parser = new XMLparse($isnormal);
$data = $xml_parser->parse($xml);
$xml_parser->destruct();
return $data;
}
function array2xml($arr, $htmlon = TRUE, $isnormal = FALSE, $level = 1) {
$s = $level == 1 ? "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\r\n<root>\r\n" : '';
$space = str_repeat("\t", $level);
foreach($arr as $k => $v) {
if(!is_array($v)) {
$s .= $space."<item id=\"$k\">".($htmlon ? '<![CDATA[' : '').$v.($htmlon ? ']]>' : '')."</item>\r\n";
} else {
$s .= $space."<item id=\"$k\">\r\n".array2xml($v, $htmlon, $isnormal, $level + 1).$space."</item>\r\n";
}
}
$s = preg_replace("/([\x01-\x08\x0b-\x0c\x0e-\x1f])+/", ' ', $s);
return $level == 1 ? $s."</root>" : $s;
}
class XMLparse {
var $parser;
var $document;
var $stack;
var $data;
var $last_opened_tag;
var $isnormal;
var $attrs = array();
var $failed = FALSE;
function __construct($isnormal) {
$this->XMLparse($isnormal);
}
function XMLparse($isnormal) {
$this->isnormal = $isnormal;
$this->parser = xml_parser_create('ISO-8859-1');
xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, false);
xml_set_object($this->parser, $this);
xml_set_element_handler($this->parser, 'open','close');
xml_set_character_data_handler($this->parser, 'data');
}
function destruct() {
xml_parser_free($this->parser);
}
function parse(&$data) {
$this->document = array();
$this->stack = array();
return xml_parse($this->parser, $data, true) && !$this->failed ? $this->document : '';
}
function open(&$parser, $tag, $attributes) {
$this->data = '';
$this->failed = FALSE;
if(!$this->isnormal) {
if(isset($attributes['id']) && !is_string($this->document[$attributes['id']])) {
$this->document = &$this->document[$attributes['id']];
} else {
$this->failed = TRUE;
}
} else {
if(!isset($this->document[$tag]) || !is_string($this->document[$tag])) {
$this->document = &$this->document[$tag];
} else {
$this->failed = TRUE;
}
}
$this->stack[] = &$this->document;
$this->last_opened_tag = $tag;
$this->attrs = $attributes;
}
function data(&$parser, $data) {
if($this->last_opened_tag != NULL) {
$this->data .= $data;
}
}
function close(&$parser, $tag) {
if($this->last_opened_tag == $tag) {
$this->document = $this->data;
$this->last_opened_tag = NULL;
}
array_pop($this->stack);
if($this->stack) {
$this->document = &$this->stack[count($this->stack)-1];
}
}
}
//***************xml 與 array 之間的轉換處理二***********************/
class xml_to_array($xml){
function xml_to_array($xml){
if(empty($xml)){
$array = array();
}else{
$array = @(array)(simplexml_load_string($xml,'SimpleXMLElement', LIBXML_NOBLANKS)); //LIBXML_NOBLANKS LIBXML_NOCDATA
//if($array==false)
{
foreach($array as $key=>$item){
$array[$key] = $this->struct_to_array((array)$item);
}
}
}
return $array;
}
function struct_to_array($item){
if(!is_string($item)) {
$item = (array)$item;
foreach($item as $key=>$val){
$item[$key] = self::struct_to_array($val);
}
}
return $item;
}
}
//***************xml 與 array 之間的轉換處理三***********************/
/**
*描述:XML文件數據讀取類(SAX 解析)
*運行環境: PHP4,PHP5 最好有 iconv() 函數支持
*用途: 用於讀取xml文件數據到一數組裡,目前還不能對一些特殊的標記進行處理
*特點: 可為同級兄弟結點指定索引(數組下標)
*@name php解析xml 方法二
*@desc 解析xml-string數據流 生成array
*/
class xmlRead
{
//解析器
var $var_parser;
//xml文件編碼語言
var $var_lang = 'GB2312';
var $var_use_iconv = 1;
//*****************************************************
// $var_node[深度][節點名] node_name
// $var_node[深度][目標類型] target_type
// $var_node[深度][目標名稱] target_name
// 目標: 屬性/子節點; 0/1
// 深度: 數字 - by Mayer
//*****************************************************
var $var_node = array();
var $var_index = array();
var $var_stack = array(); //標記棧
var $var_stack_attrs = array(); //參數棧
//節點深度
var $var_depth = 0;
// $var_data[深度]; $var_data[0] 用來存 xml文件所有記錄
var $var_data = array(); //數據
var $var_data_str = '';
/******************************************************
* 構造函數 -by Mayer 2005-1-17
******************************************************/
function xmlRead($lang='GB2312')
{
if('UTF-8' == strtoupper($lang))
{
$this->var_parser = xml_parser_create('UTF-8');
}
else
{
$this->var_parser = xml_parser_create();
if('GBK' == strtoupper($lang))
{
$this->var_lang = $lang;
}
}
xml_set_object($this->var_parser,&$this);
xml_parser_set_option($this->var_parser, XML_OPTION_CASE_FOLDING, 0);
xml_set_element_handler($this->var_parser, "startElement", "endElement");
xml_set_character_data_handler($this->var_parser, "characterData");
}
/******************************************************
* 配置節點索引 -by Mayer 2005-1-17
******************************************************/
function xmlRead_node_config($node = '')
{
if(is_array($node))
{
$this->var_node = $node;
}
}
/******************************************************
* 配置節點索引 -by Mayer 2005-1-17
******************************************************/
function xmlRead_set_use_iconv($value)
{
$this->var_use_iconv = intval($value);
}
/******************************************************
* 獲取xml數據記錄 -by Mayer 2005-1-17
******************************************************/
function xmlRead_get_ret()
{
return $this->var_data[0];
}
function xmlRead_parser_file($file,$is_code=0)
{
if(!$is_code)
{
if (!($fp = fopen($file, "r")))
{
//die("could not open XML input");
die();
}
$data = fread($fp, 4096);
}
else
{
$data = $file;
$fp = 0;
}
if('GBK' == $this->var_lang)
{
//$data = str_replace(array('utf-8','gb2312','UTF-8','GB2312'),'GBK',$data);
$data = preg_replace("/encoding=(.+)\?\>/",'encoding="GBK" ?>',$data);
}
elseif('UTF-8' == $this->var_lang)
{
}
if($fp)
{
do
{
if(!xml_parse($this->var_parser, $data, feof($fp)))
{
die(sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($this->var_parser)),
xml_get_current_line_number($this->var_parser)
)
);
}
}while($data = fread($fp, 4096));
}
else
{
xml_parse($this->var_parser, $data);
}
xml_parser_free($this->var_parser);
}
function startElement($parser, $name, $attrs)
{
if(function_exists('iconv') && $this->var_use_iconv )
{
$name = iconv('UTF-8', $this->var_lang, $name);
}
//節點開始, 節點名入棧
array_push($this->var_stack,$name);
array_push($this->var_stack_attrs,$attrs);
//設置節點深度
$this->var_depth = count($this->var_stack) - 1;
if($this->var_depth > 0)
{
//判斷現在是否只有一個同級同名兄弟結點
// 當前深度標識的數據是否為一數組 && 是否存在同級同名索引為 $this->var_index[$this->var_depth][$name]] 的記錄存在
// 或同級同名兄弟結點數據為字符串
if(is_array($this->var_data[$this->var_depth][$name]) && !isset($this->var_data[$this->var_depth][$name][$this->var_index[$this->var_depth][$name]]) || is_string($this->var_data[$this->var_depth][$name]))
{
//判斷是否有索引設置
if($this->var_node[$this->var_depth]['node_name'] == $name)
{
//如果索引值不存在...
if(!$this->var_index[$this->var_depth][$name])
{
if(intval($this->var_node[$this->var_depth]['target_type']) == 1)
{
$index = $this->var_data[$this->var_depth][$name][$this->var_node[$this->var_depth]['target_name']];
if(is_array($index))
{
$this->var_index[$this->var_depth][$name] = 0;
}
}
else
{
$this->var_index[$this->var_depth][$name] = $attrs[$this->var_node[$this->var_depth]['target_name']];
}
}
}
else
{
$this->var_index[$this->var_depth][$name] = 0;
}
if($this->var_node[$this->var_depth]['fun'])
{
eval("\$this->var_index[$this->var_depth][$name]={$this->var_node[$this->var_depth]['fun']}('{$this->var_index[$this->var_depth][$name]}');\n");
}
$this->var_data[$this->var_depth][$name] = array($this->var_index[$this->var_depth][$name]=>$this->var_data[$this->var_depth][$name]);
}
}
//檢查節點類型,
}
function endElement($parser, $name)
{
if(function_exists('iconv') && $this->var_use_iconv )
{
$name = iconv('UTF-8', $this->var_lang, $name);
}
//判斷下級結點數據是否存在
if(is_array($this->var_data[$this->var_depth+1]) && count($this->var_data[$this->var_depth+1]))
{
//判斷同級結點是否存在 如在標簽結束時同級結點存在的話那在這級同名結點為多數 同級同名首結點在startElement裡判斷並重命名索引
//同級同名索引存在否 && 同級同名索引數據存在否
if(isset($this->var_index[$this->var_depth][$name]) && isset($this->var_data[$this->var_depth][$name][$this->var_index[$this->var_depth][$name]]))
{
//判斷是否要設置結點索引
if($this->var_node[$this->var_depth]['node_name'] == $name)
{
if($this->var_node[$this->var_depth]['target_type'] == 0)
{
$attrs = end($this->var_stack_attrs);
if(count($attrs))
{
$index = $attrs[$this->var_node[$this->var_depth]['target_name']];
}
}
else
{
$index = $this->var_data[$this->var_depth+1][$this->var_node[$this->var_depth]['target_name']];
}
if($this->var_node[$this->var_depth]['fun'])
{
eval("\$index={$this->var_node[$this->var_depth]['fun']}('$index');\n");
}
$this->var_data[$this->var_depth][$name][$index] = $this->var_data[$this->var_depth+1];
}
else
{
$this->var_data[$this->var_depth][$name][] = $this->var_data[$this->var_depth+1];
}
}
else
{
$this->var_data[$this->var_depth][$name] = $this->var_data[$this->var_depth+1];
//在還沒有同級結點的時候,判斷是否要設置索引
if($this->var_node[$this->var_depth]['node_name'] == $name)
{
if(intval($this->var_node[$this->var_depth]['target_type']) == 1)
{
$index = $this->var_data[$this->var_depth][$name][$this->var_node[$this->var_depth]['target_name']];
if(is_array($index))
{
$index = 0;
}
}
else
{
$attrs = end($this->var_stack_attrs);
$index = $attrs[$this->var_node[$this->var_depth]['target_name']];
}
//設置索引值
$this->var_index[$this->var_depth][$name] = $index;
}
else
{
//索引默認為 0
$this->var_index[$this->var_depth][$name] = 0;
}
}
}
unset($this->var_data[$this->var_depth+1]);
unset($this->var_index[$this->var_depth+1]);
//print_r($this->var_data[$this->var_depth][$name]);
//echo " : $name<br>";
//節點結束, 節點名出棧
array_pop($this->var_stack);
array_pop($this->var_stack_attrs);
$this->var_depth = count($this->var_stack) - 1;
$this->var_data_str = '';
}
function characterData($parser,$data)
{
$this->var_data_str.=$data;
if(trim($this->var_data_str) !== '')
{
$name = end($this->var_stack);
if(($name == 'ta' || $name == 'le' || $name == 'tb') && !strstr($data,','))
{
//return;
}
if(function_exists('iconv') && $this->var_use_iconv )
{
$this->var_data_str = iconv('UTF-8', $this->var_lang, $this->var_data_str);
}
//echo $data."<br>";
//判斷是否已經有同級並同名的記錄存在
if(is_array($this->var_data[$this->var_depth][$name]))
{
//判斷是否要設置結點索引
if($this->var_node[$this->var_depth]['node_name'] == $name && $this->var_node[$this->var_depth]['target_type'] == 0)
{
$attrs = end($this->var_stack_attrs);
if(count($attrs))
{
$index = $attrs[$this->var_node[$this->var_depth]['target_name']];
}
$this->var_data[$this->var_depth][$name][$index] = $this->var_data_str;
}
else
{
$this->var_data[$this->var_depth][$name][] = $this->var_data_str;
}
}
else
{
$this->var_data[$this->var_depth][$name] = $this->var_data_str;
//在還沒有同級結點的時候,判斷是否要設置索引
if($this->var_node[$this->var_depth]['node_name'] == $name && $this->var_node[$this->var_depth]['target_type'] == 0)
{
$attrs = end($this->var_stack_attrs);
$index = $attrs[$this->var_node[$this->var_depth]['target_name']];
//設置索引值
$this->var_index[$this->var_depth][$name] = $index;
}
else
{
//索引默認為 0
$this->var_index[$this->var_depth][$name] = 0;
}
}
}
}
function convert_xml($target,$value)
{
if(!is_numeric(substr($target,0,1)) && trim($target)!='')
{
array_push($this->var_stack,$target);
}
$tag = end($this->var_stack);
if(is_array($value))
{
list($tmp,) = each($value);
if(!is_numeric(substr($tmp,0,1)) && trim($tmp)!='')
{
$xml_code.="<$tag>";
}
foreach($value as $key => $val)
{
$xml_code.=$this->convert_xml($key,$val);
}
if(!is_numeric(substr($tmp,0,1)) && trim($tmp)!='')
{
$xml_code.="</$tag>";
}
}
else
{
if(strchr($value,'"'))
{
$xml_code.="<$tag><![CDATA[$value]]> </$tag>\n";
}
else $xml_code.="<$tag>$value</$tag>";
}
if(!is_numeric(substr($target,0,1)) && trim($target)!='')
{
array_pop($this->var_stack);
}
return $xml_code;
}
}
//使用示例
$this->xml_client = new xmlRead('UTF-8'); //設置語言 UTF-8 gb2312
$this->xml_client->var_use_iconv = 0; //是否使用 iconv
$this->xml_client->xmlRead_parser_file($xml,1); //解析文件
$array = $this->xml_client->xmlRead_get_ret(); //得到數組
if(!empty($array)) $res_arr = $array;
else $res_arr = array();
//***************xml 與 array 之間的轉換處理四***********************/
/**
*@name array2xml 將一維數組轉化為xml格式字符串輸出
*@retrn $xml-string for xml type
*/
function array_to_xml($arr,$encoding)
{
$encoding = $encoding=='' ? 'ISO-8859-1':$encoding;
if(!empty($arr)){
$obj_dom = new DOMDocument("1.0",$encoding);
//header("Content-Type: text/plain");
$root = $obj_dom->createElement($arr[0],'');
$obj_dom->appendChild($root);
foreach($arr as $rk=>$rv){
if($rk!='0'){
$item = $obj_dom->createElement($rk,$rv);
$root->appendChild($item);
}
}
$xml = $obj_dom->saveXMl();
}
else $xml = '';
return $xml;
}
//調用示例
$req_arr = array('request','msgType'=>'SvtGet3GUserInfReq','uid'=>'123456789','pageSize'=>1,'pageNo'=>0);
$encoding = 'UTF-8';
$xml = array_to_xml($req_arr,$encoding);
echo $xml;
?>