PHP XML操作类 xml2array -- 含节点属性大屏查看

发布于:2016年06月08日 已被阅读

1. 单向xml2array函数

 

Php代码  收藏代码

  1. function xml2array($contents$get_attributes=1, $priority = 'tag')   

  2. {  

  3.     if(!$contentsreturn array();   

  4.   

  5.     if(!function_exists('xml_parser_create')) {  

  6.         //print "'xml_parser_create()' function not found!";  

  7.         return array();  

  8.     }   

  9.   

  10.     //Get the XML parser of PHP - PHP must have this module for the parser to work  

  11.     $parser = xml_parser_create('');  

  12.     xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8"); # http://minutillo.com/steve/weblog/2004/6/17/php-xml-and-character-encodings-a-tale-of-sadness-rage-and-data-loss  

  13.     xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);  

  14.     xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);  

  15.     xml_parse_into_struct($parser, trim($contents), $xml_values);  

  16.     xml_parser_free($parser);   

  17.   

  18.     if(!$xml_valuesreturn;//Hmm...   

  19.   

  20.     //Initializations  

  21.     $xml_array = array();  

  22.     $parents = array();  

  23.     $opened_tags = array();  

  24.     $arr = array();   

  25.   

  26.     $current = &$xml_array//Refference   

  27.   

  28.     //Go through the tags.  

  29.     $repeated_tag_index = array();//Multiple tags with same name will be turned into an array  

  30.     foreach($xml_values as $data) {  

  31.         unset($attributes,$value);//Remove existing values, or there will be trouble   

  32.   

  33.         //This command will extract these variables into the foreach scope  

  34.         // tag(string), type(string), level(int), attributes(array).  

  35.         extract($data);//We could use the array by itself, but this cooler.   

  36.   

  37.         $result = array();  

  38.         $attributes_data = array();   

  39.   

  40.         if(isset($value)) {  

  41.             if($priority == 'tag'$result = $value;  

  42.             else $result['value'] = $value//Put the value in a assoc array if we are in the 'Attribute' mode  

  43.         }   

  44.   

  45.         //Set the attributes too.  

  46.         if(isset($attributesand $get_attributes) {  

  47.             foreach($attributes as $attr => $val) {  

  48.                 if($priority == 'tag'$attributes_data[$attr] = $val;  

  49.                 else $result['attr'][$attr] = $val//Set all the attributes in a array called 'attr'  

  50.             }  

  51.         }   

  52.   

  53.         //See tag status and do the needed.  

  54.         if($type == "open") {//The starting of the tag '<tag>'  

  55.             $parent[$level-1] = &$current;  

  56.             if(!is_array($currentor (!in_array($tagarray_keys($current)))) { //Insert New tag  

  57.                 $current[$tag] = $result;  

  58.                 if($attributes_data$current[$tag'_attr'] = $attributes_data;  

  59.                 $repeated_tag_index[$tag.'_'.$level] = 1;   

  60.   

  61.                 $current = &$current[$tag];   

  62.   

  63.             } else { //There was another element with the same tag name   

  64.   

  65.                 if(isset($current[$tag][0])) {//If there is a 0th element it is already an array  

  66.                     $current[$tag][$repeated_tag_index[$tag.'_'.$level]] = $result;  

  67.                     $repeated_tag_index[$tag.'_'.$level]++;  

  68.                 } else {//This section will make the value an array if multiple tags with the same name appear together  

  69.                     $current[$tag] = array($current[$tag],$result);//This will combine the existing item and the new item together to make an array  

  70.                     $repeated_tag_index[$tag.'_'.$level] = 2;   

  71.   

  72.                     if(isset($current[$tag.'_attr'])) { //The attribute of the last(0th) tag must be moved as well  

  73.                         $current[$tag]['0_attr'] = $current[$tag.'_attr'];  

  74.                         unset($current[$tag.'_attr']);  

  75.                     }   

  76.   

  77.                 }  

  78.                 $last_item_index = $repeated_tag_index[$tag.'_'.$level]-1;  

  79.                 $current = &$current[$tag][$last_item_index];  

  80.             }   

  81.   

  82.         } elseif($type == "complete") { //Tags that ends in 1 line '<tag />'  

  83.             //See if the key is already taken.  

  84.             if(!isset($current[$tag])) { //New Key  

  85.                 $current[$tag] = $result;  

  86.                 $repeated_tag_index[$tag.'_'.$level] = 1;  

  87.                 if($priority == 'tag' and $attributes_data$current[$tag'_attr'] = $attributes_data;   

  88.   

  89.             } else { //If taken, put all things inside a list(array)  

  90.                 if(isset($current[$tag][0]) and is_array($current[$tag])) {//If it is already an array...   

  91.   

  92.                     // ...push the new element into that array.  

  93.                     $current[$tag][$repeated_tag_index[$tag.'_'.$level]] = $result;   

  94.   

  95.                     if($priority == 'tag' and $get_attributes and $attributes_data) {  

  96.                         $current[$tag][$repeated_tag_index[$tag.'_'.$level] . '_attr'] = $attributes_data;  

  97.                     }  

  98.                     $repeated_tag_index[$tag.'_'.$level]++;   

  99.   

  100.                 } else { //If it is not an array...  

  101.                     $current[$tag] = array($current[$tag],$result); //...Make it an array using using the existing value and the new value  

  102.                     $repeated_tag_index[$tag.'_'.$level] = 1;  

  103.                     if($priority == 'tag' and $get_attributes) {  

  104.                         if(isset($current[$tag.'_attr'])) { //The attribute of the last(0th) tag must be moved as well   

  105.   

  106.                             $current[$tag]['0_attr'] = $current[$tag.'_attr'];  

  107.                             unset($current[$tag.'_attr']);  

  108.                         }   

  109.   

  110.                         if($attributes_data) {  

  111.                             $current[$tag][$repeated_tag_index[$tag.'_'.$level] . '_attr'] = $attributes_data;  

  112.                         }  

  113.                     }  

  114.                     $repeated_tag_index[$tag.'_'.$level]++; //0 and 1 index is already taken  

  115.                 }  

  116.             }   

  117.   

  118.         } elseif($type == 'close') { //End of tag '</tag>'  

  119.             $current = &$parent[$level-1];  

  120.         }  

  121.     }   

  122.   

  123.     return($xml_array);  

  124. }  

 

$priority设置为空的时候,可以获取所有节点属性值。

 

优点: 获取的节点属性不占用数组父级键。

缺点: $priority设置为tag时,获取节点属性值不太理想。

 

 

2. 双向xml2array和array2xml函数

 

Php代码  收藏代码

  1. <?php   

  2.   

  3. ###################################################################################   

  4. # xml2array: takes raw XML as a parameter (a string)   

  5. and returns an equivalent PHP data structure   

  6. ###################################################################################   

  7. function & xml2array(&$xml,$attr=true){   

  8.     $xml_parser = &new XML();   

  9.     $xml_parser->attr = $attr;   

  10.     $data = &$xml_parser->parse($xml);   

  11.     $xml_parser->destruct();   

  12.     return $data;   

  13. }   

  14. ###################################################################################   

  15. # array2xml: serializes any PHP data structure into XML   

  16. # Takes one parameter: the data to serialize. Must be an array.   

  17. ###################################################################################   

  18. function & array2xml(&$data$level = 0, $prior_key = NULL){   

  19.     if($level == 0){ ob_start(); echo '<?xml version="1.0" ?>',"\n"; }   

  20.     while(list($key$value) = each($data))   

  21.         if(!strpos($key'_attr')) #if it's not an attribute   

  22.             #we don't treat attributes by themselves, so for an emptyempty element   

  23.             # that has attributes you still need to set the element to NULL   

  24.   

  25.             if(is_array($valueand array_key_exists(0, $value)){   

  26.                 array2xml($value$level$key);   

  27.             }else{   

  28.                 $tag = $prior_key ? $prior_key : $key;   

  29.                 echo str_repeat("\t"$level),'<',$tag;   

  30.                 if(array_key_exists($key.'_attr'$data)){ #if there's an attribute for this element   

  31.                     while(list($attr_name$attr_value) = each($data[$key.'_attr']))   

  32.                         echo ' ',$attr_name,'="',htmlspecialchars($attr_value),'"';   

  33.                     reset($data[$key.'_attr']);   

  34.                 }   

  35.   

  36.                 if(is_null($value)) echo " />\n";   

  37.                 elseif(!is_array($value)) echo '>',htmlspecialchars($value),"</$tag>\n";   

  38.                 else echo ">\n",array2xml($value$level+1),str_repeat("\t"$level),"</$tag>\n";   

  39.             }   

  40.     reset($data);   

  41.     if($level == 0){ $str = &ob_get_contents(); ob_end_clean(); return $str; }   

  42. }   

  43. ###################################################################################   

  44. # XML class: utility class to be used with PHP's XML handling functions   

  45. ###################################################################################   

  46. class XML  

  47. {   

  48.     var $parser;   #a reference to the XML parser   

  49.     var $document; #the entire XML structure built up so far   

  50.     var $parent;   #a pointer to the current parent - the parent will be an array   

  51.     var $stack;    #a stack of the most recent parent at each nesting level   

  52.     var $last_opened_tag; #keeps track of the last tag opened.   

  53.     var $attr = true;  

  54.   

  55.     function XML()  

  56.     {   

  57.         $this->parser = &xml_parser_create();   

  58.         xml_parser_set_option(&$this->parser, XML_OPTION_CASE_FOLDING, false);   

  59.         xml_set_object(&$this->parser, &$this);   

  60.         xml_set_element_handler(&$this->parser, 'open','close');   

  61.         xml_set_character_data_handler(&$this->parser, 'data');   

  62.     }   

  63.     function destruct(){ xml_parser_free(&$this->parser); }   

  64.     function & parse(&$data)  

  65.     {   

  66.         $this->document = array();   

  67.         $this->stack    = array();   

  68.         $this->parent   = &$this->document;   

  69.         return xml_parse(&$this->parser, &$data, true) ? $this->document : NULL;   

  70.     }   

  71.     function open(&$parser$tag$attributes)  

  72.     {   

  73.         $this->data = '';    

  74.         #stores temporary cdata  

  75.         $this->last_opened_tag = $tag;   

  76.         #if you've seen this tag before  

  77.         if(is_array($this->parent) and array_key_exists($tag,$this->parent))  

  78.         {    

  79.             #if the keys are numeric  

  80.             #this is the third or later instance of $tag we've come across   

  81.             if(is_array($this->parent[$tag]) and array_key_exists(0,$this->parent[$tag])) $key = $this->count_numeric_items($this->parent[$tag]);   

  82.             else  

  83.             {   

  84.                 #this is the second instance of $tag that we've seen. shift around   

  85.                 if(array_key_exists($tag.'_attr',$this->parent))  

  86.                 {   

  87.                     $arr = array('0_attr'=>&$this->parent[$tag.'_attr'], &$this->parent[$tag]);   

  88.                     unset($this->parent[$tag.'_attr']);   

  89.                 }  

  90.                 else $arr = array(&$this->parent[$tag]);   

  91.                   

  92.                 $this->parent[$tag] = &$arr;   

  93.                 $key = 1;   

  94.             }   

  95.             $this->parent = &$this->parent[$tag];   

  96.         }  

  97.         else $key = $tag;   

  98.   

  99.         if($attributes AND $this->attr) $this->parent[$key.'_attr'] = $attributes;   

  100.         $this->parent  = &$this->parent[$key];   

  101.         $this->stack[] = &$this->parent;   

  102.     }   

  103.     function data(&$parser$data)  

  104.     {   

  105.         #you don't need to store whitespace in between tags  

  106.         if($this->last_opened_tag != NULL) $this->data .= $data;   

  107.     }   

  108.     function close(&$parser$tag)  

  109.     {   

  110.         if($this->last_opened_tag == $tag)  

  111.         {   

  112.             $this->parent = $this->data;   

  113.             $this->last_opened_tag = NULL;   

  114.         }   

  115.         array_pop($this->stack);   

  116.         if($this->stack) $this->parent = &$this->stack[count($this->stack)-1];   

  117.     }   

  118.     function count_numeric_items(&$array)  

  119.     {   

  120.         return is_array($array) ? count(array_filter(array_keys($array), 'is_numeric')) : 0;   

  121.     }   

  122. }   

   

 

实例:

 

Php代码  收藏代码

  1. <?php  

  2. include('xml.php');  

  3. $data = xml2array($xml);  

  4. ?>   

 

Php代码  收藏代码

  1. <?php  

  2. include('xml.php');  

  3. $xml = array2xml($data);  

  4. ?>   

 

来源: http://keithdevens.com/software/phpxml

该类已根据来源代码做了修改。

 

如果$attr设置为false,输出的数组中将不包括节点属性值。

 

优点: 获取节点属性值较理想。

缺点: 获取的节点属性占用数组父级键


最新发布
linux下svn提交忽略某些文件... (119)
使用批处理来批量更新、提交SVN... (116)
linux查看目录文件大小命令 (117)
linux tar打包压缩排除某个... (114)
Linux tar压缩和解压 (116)
SVN子命令add用法浅析 (111)
热门博文
网友FBI探案:马蓉iPad惊人发现... (43320)
优衣库这个广告拍的很真实,反应人性,... (10110)
霍金携手俄罗斯富豪耗资1亿美元寻找外... (4734)
如何才能查看PHP内置函数源代码... (1196)
微信支付开发当前URL未注册的解决方... (514)
《谁为爱情买单》中的经典面试 ... (414)
精华博文
[推荐]Centos7 安装配置 SVN (117)
easyswoole框架安装 (115)
php开启pecl的支持(推荐) (116)
1-10个恋爱表现:男朋友爱你程度到... (119)
女生喜欢你的10个程度,到第六个就可... (121)
Eclipse 没有Server选项... (153)
友情链接
我来忙 (110)