设为首页 收藏本站
查看: 802|回复: 0

[经验分享] php解析xml,并将xml转换为层级数组

[复制链接]

尚未签到

发表于 2018-12-17 11:15:28 | 显示全部楼层 |阅读模式
  1)xml_parser_create([ string $encoding ] ):建立一个新的xml解析器并返回可被其他xml函数使用的资源句柄,
  参数$encoding:
  php4,中用来只指定要被解析的xml输入的字符编码方式;
  php5,自动侦测输入xml的编码,encoding仅用来指定解析后输出数据的编码
  默认:输入编码=输出编码
  php5.0.2+默认编码utf-8;之前版本,ISO-8859-1
  2)bool xml_parser_set_option(resource $parser,int $option,mixed $value):为指定的的xml解析进行选项设置
  parser:指向要设置选项信息的xml解析器指针
  option:要设置选项的名称
  value:要设置选项的值
  设置成功返回true,失败返回false
  选项数据类型描述
  XML_OPTION_CASE_FOLDINGint 控制在该xml解析器中大小写是否有效。默认有效,0原样输出,1转换为大写,只控制输出样式
  XML_OPTION_SKIP_TAGSTARTint 指明在一个标记名前应略过几个字符
  XML_OPTION_SKIP_WHITEint 是否略过由空白字符组成的值
  XML_OPTION_TARGET_ENCODINGstring
  3)int xml_parse_into_struct(resource $parser,string $data,array &$values [,array &$index]):将xml
  文件解析到两个对应的数组中,index参数含有指向values数组中对应值的指针,该函数返回的是一级数组,不想dom树那样有层级关系
  失败返回0,成功返回1
  4)eg:
  源文件:
  
  
      aaaa
     
     
  
  value结果:
  Array
  (
      [0] => Array
          (
          //标签名
              [tag] => newdata
              //节点状态,open:含有子标签,起始标签;close:open的闭合部分;complete:无子标签
              [type] => open
              //层级
              [level] => 1
          )
  

      [1] => Array
          (
              [tag] => version
              [type] => complete
              [level] => 2
              //节点属性数组
              [attributes] => Array
                  (
                      [a] => xxx
                  )
              //节点值
              [value] => aaaa
          )
  

      [2] => Array
          (
              [tag] => sample
              [type] => complete
              [level] => 2
              [value] => 0
          )
  

      [3] => Array
          (
              [tag] => all
              [type] => complete
              [level] => 2
              [value] => https
          )
  

      [4] => Array
          (
              [tag] => newdata
              [type] => close
              [level] => 1
          )
  

  )
  索引结果:
  Array
  (
  //节点名称
      [newdata] => Array
          (
              [0] => 0//节点起始索引
              [1] => 4//节点结束索引
          )
  

      [version] => Array
          (
              [0] => 1
          )
  

      [sample] => Array
          (
              [0] => 2
          )
  

      [all] => Array
          (
              [0] => 3
          )
  

  )
  5)将xml转换为array的函数:
  /**
  * 将xml字符串转换为数组
  * @param string $contents
  * @param string $encoding
  * @param int $get_attrbutes
  * @param string $priority
  * @param array
  */
  public static function xml2Array($contents = NULL, $encoding = 'UTF-8', $get_attributes = 1, $priority = 'tag') {
  if(!$contents) {
  return array();
  }
  if(!function_exists('xml_parser_create')) {
  return array();
  }
  //xml解析器
  $parser = xml_parser_create('');
  xml_parser_set_option($parser,XML_OPTION_TARGET_ENCODING,$encoding);
  //将标签原样输出,不转换成大写
  xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0);
  //是否忽略空白字符
  xml_parser_set_option($parser,XML_OPTION_SKIP_WHITE,1);
  //$xml_values,$index引用类型,将文本解析到指定的数组变量中
  xml_parse_into_struct($parser, trim($contents), $xml_values/*,$index*/);
  //释放解析器
  xml_parser_free($parser);
  if(!$xml_values)
  return array();
  $xml_array = array();
  $parents = array();
  $opened_tags = array();
  $arr = array();
  //当前操作结构的指针
  $current = & $xml_array;
  //同级结构下重复标签的计数
  $repeated_tag_index = array();
  foreach ($xml_values as $data) {
  //删除属性和值,确保每次用到的是新的
  unset($attributes, $value);
  //将标签结构数组,释放到当前的变量域中
  extract($data);
  //存当前标签的结果
  $result = array();
  //存属性
  $attributes_data = array();
  //标签有value
  if(isset($value)) {
  if($priority == 'tag'){
  $result = trim($value);
  }else{
  $result['value'] = trim($value);
  }
  }
  //标签有属性,且不忽略
  if($get_attributes && isset($attributes)) {
  foreach ($attributes as $attr => $val) {
  if ($priority == 'tag'){//放入单独记录属性的数组中
  $attributes_data[$attr] = $val;
  }else{//统一放入$result中
  $result['attr'][$attr] = $val;
  }
  }
  }
  //处理节点关系
  if ($type == "open") {//有子节点标签
  $parent[$level - 1] = & $current; //$parent[$level - 1],指向复合标签的起始处
  if (!is_array($current) || (!in_array($tag, array_keys($current)))) {//xml复合标签的第一个
  $current[$tag] = $result;//属性独立
  /*处理结果
  [tag] => Array
  (
  [value] => aaaa,
  [attr] => Array
  (
  [a] => xxx
  )
  

  )
  */
  if ($attributes_data){
  $current[$tag . '_attr'] = $attributes_data;
  /*处理结果
  [tag] => xxxx,
  [tag_attr] => Array
  (
  [a] => xxx
  )
  */
  }
  $repeated_tag_index[$tag . '_' . $level] = 1;//记录同级中该标签重复的个数
  //指针重新指向符合标签的子标签
  $current = & $current[$tag];
  }else {
  if (isset($current[$tag][0])) {//第3+个同级复合标签
  $current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result;
  $repeated_tag_index[$tag . '_' . $level] ++;
  } else {//第2个同级复合标签
  //在关联数组外包一层索引数组
  $current[$tag] = array(
  $current[$tag],
  $result
  );
  $repeated_tag_index[$tag . '_' . $level] = 2;
  //此处只记录第一个重复标签的属性,可能有bug,需注意!
  //要想区别各子标签的属性,需要将$priority设成非'tag'
  if (isset($current[$tag . '_attr'])) {
  $current[$tag]['0_attr'] = $current[$tag . '_attr'];
  unset($current[$tag . '_attr']);
  }
  }
  //记录最后一个重复子标签的索引
  $last_item_index = $repeated_tag_index[$tag . '_' . $level] - 1;
  //指针指向下一个子标签
  $current = & $current[$tag][$last_item_index];
  }
  } elseif ($type == "complete") {
  //第一个complete类型的标签
  if (!isset($current[$tag])) {
  $current[$tag] = $result;
  $repeated_tag_index[$tag . '_' . $level] = 1;
  if ($priority == 'tag' && $attributes_data)
  $current[$tag . '_attr'] = $attributes_data;
  }
  else {
  //第3+个同级子标签
  //此处只有$current[$tag][0],不行,因为可能索引到字符串的第一个字符
  if(isset($current[$tag][0]) && !is_array($current[$tag])){
  print_r($current);exit();
  }
  if(isset($current[$tag][0]) && is_array($current[$tag])) {
  $current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result;
  //子标签的属性不忽略
  if ($get_attributes &&  $priority == 'tag' && $attributes_data) {
  $current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data;
  }
  $repeated_tag_index[$tag . '_' . $level] ++;
  }else{//第2个同级子标签
  $current[$tag] = array(
  $current[$tag],
  $result
  );
  $repeated_tag_index[$tag . '_' . $level] = 1;
  if ($priority == 'tag' && $get_attributes) {
  if (isset($current[$tag . '_attr'])) {
  $current[$tag]['0_attr'] = $current[$tag . '_attr'];
  unset($current[$tag . '_attr']);
  }
  if ($attributes_data) {
  $current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data;
  }
  }
  $repeated_tag_index[$tag . '_' . $level] ++;
  }
  }
  }elseif($type == 'close'){
  //闭合标签和起始标签level相同,因此进入complete类型的子标签后,可以通过父节点的close标签,可以指回到父节点
  $current = & $parent[$level - 1];
  }
  }
  return $xml_array;
  }
  6)关于xml中的CDATA:
  在XML文档中的所有文本都会被解析器解析。只有在CDATA部件之内的文本会被解析器忽略
    一个 CDATA 部件以"< ![CDATA[" 标记开始,以"]]>"标记结束:
    < script>
    < ![CDATA[
    function matchwo(a,b)
    {
        if (a < b && a < 0) then
        {
            return 1
        }
        else
        {
            return 0
        }
      }
     ]]>
    < /script>
    在前面的例子中,所有在CDATA部件之间的文本都会被解析器忽略。
    CDATA注意事项:
    CDATA部件之间不能再包含CDATA部件(不能嵌套)。如果CDATA部件包含了字符"]]>" 或者"< !        [CDATA[" ,将很有可能出错哦。
    同样要注意在字符串"]]>"之间没有空格或者换行符
  参考地址:http://www.cnblogs.com/chenqingwei/archive/2010/04/21/1717237.html




运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-652377-1-1.html 上篇帖子: php5.6 源码安装过程 下篇帖子: php开启短标签
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表