php下哪种方法合适解析xml,转换成json格式

解析xml文档的类库有很多种,比较常用的就是SimpleXML,DOM Document,XMLReader,基于SAX的xml_parse函数。

根据xml文档结构,以及需求的不同,要选择好对应的类库。

解析小的文档的话,使用SimpleXML比较合适,简单的几个函数就可以搞定。

如果文档非常巨大,最好是XMLReader打开,中间转换成DOM来解析,感觉DOM与XPath结合的比较好。

以上是解析已知文档结构的XML,比如知道使用了什么命名空间,有哪些主要的节点等等信息的XML文档。

如果是要解析任意的XML文档,还是SAX的xml_parse比较合适,自己定义三个handler函数。

比如笔者就是用xml_parse来解析任意的xml文档,生成json格式的字符串。

 

 

下面把使用xml_parse来解析xml文档的所需要的三个handler讲解一遍。

 

首先是三个变量

$depth是指xml文档结构的层数,第一层的值是0。

$json_array是一个多位数组,每一个元素的成员是一个json数组,直接可以用json_encode函数。

这个数组的第一维的index是上面的$depth,解析完每一层的xml结构后,都将其结果"粘贴"到其父节点的最后一个字节点后边。

解析完成后$json_array[0]就是所有的xml文档内容都在里面啦。

$tag_name_stack也是一个数组,后进先出的数组,正在处理的标签名就存在这里面,处理完一个标签后,就将其请出数组。

 

 

 

首先是把该标签的属性都装入一个数组
foreach ($attrs as $attr_name => $attr_value) {
      $attr_name = str_replace(":", "$", $attr_name);
      $arrts_array[$attr_name]=$attr_value;
}

 

$tag_name = str_replace(":", "$", $name);
$this->tag_name_stack[] = $tag_name; // 标签名入栈

$this->depth++;  // 层数递增

 

// 将属性值放入json_array中
$this->json_array[$this->depth][$tag_name] = $arrts_array;

}

 

 

下面的cdata_handler就是处理标签的text文本或者cdata文本

 

 

 

// 在json_array中,文本信息用$t来作为index

// 这个isset的判断是因为, cdata_handler不像start_handler和end_handler只是进入一次,

// 要注意哦,cdata_handler函数,是有可能进入多次的哦,所以要用isset判断,以及.=操作符。

// 关于cdata_handler的多次进入,请参考:

http://jp2.php.net/manual/en/function.xml-set-character-data-handler.php

"ken at positive-edge dot com " 这个家伙的回复。

 

if (!isset($this->json_array[$this->depth][$tag_name]["/$t"])) {
      //$this->json_array[$this->depth][$tag_name] = array("/$t" => $data);
      $this->json_array[$this->depth][$tag_name]["/$t"] = $data;
} else {
      $this->json_array[$this->depth][$tag_name]["/$t"] .= $data;
}

 

 

最后就是end_handler,这里最重要,处理完的标签,要找准自己的父节点,

要跟在父节点的最后一个子节点后面,不要不小心把自己的兄弟姐妹都给覆盖了哦。

而且,如果有跟自己同名的兄弟姐妹的话,也要能够正确处理!

 

 

private function end_handler($parser, $name) {

                // 因为已经调用过了start_handler和cdata_handler,所以自己后面也会拖家带口的,属性啦,文本啦,子节点啦

                // 全都把他们先提取出来
                $current_tag_name = $this->tag_name_stack[$this->depth];
                $current_element = $this->json_array[$this->depth][$current_tag_name];


                if ($this->depth > 0) { // depth是0的话,这就是根节点啦,不用找父节点和处理兄弟姐妹关系了

                        // 找出父节点的标签名
                        $parent_tag_name = $this->tag_name_stack[$this->depth-1];

                        // 父节点,那就是上一层咯,这里就是判断自己有没有同名的兄弟姐妹了。
                        if (!array_key_exists($current_tag_name, $this->json_array[$this->depth-1][$parent_tag_name])) {

                                // 没有同名兄弟姐妹?那敢情好,直接挂到父节点上就ok了,

                                // 要注意最后一个[]哦,自己的标签名作为index,不要忘记了这是json数组
                                $this->json_array[$this->depth-1][$parent_tag_name][$current_tag_name] = $current_element;
                        } else {

                                // 我不寂寞,我是有同名兄弟姐妹的,这里的$child就是我的同名兄弟姐妹了。
                                $child = $this->json_array[$this->depth-1][$parent_tag_name][$current_tag_name];
                                if (isset($child[0])) {

                                        // 如果$child数组有0作为index的元素,说明我不只是一个同名兄弟姐妹哦
                                        $this->json_array[$this->depth-1][$parent_tag_name][$current_tag_name][] = $current_element;
                                } else {

                                        // 前面只有一个同名兄弟姐妹,我们要组成一个数组,然后才给$current_tag_name

                                        // 下次如果还有另外一名同名兄弟姐妹,那么它就会进入前面的分支
                                        unset($this->json_array[$this->depth-1][$parent_tag_name][$current_tag_name]);
                                        $this->json_array[$this->depth-1][$parent_tag_name][$current_tag_name][] = $child;
                                        $this->json_array[$this->depth-1][$parent_tag_name][$current_tag_name][] = $current_element;
                                }
                        }
                        array_pop($this->tag_name_stack); // 最后一个,也就是正在处理的标签名出栈

 

                        // unset这一层的数组。因为都粘到父节点上去了,自己这一层的数组没必要保留,

                        // 不过保留也可以,但是在处理下一个同层的兄弟姐妹时,要记得把我覆盖掉哦!
                         unset($this->json_array[$this->depth]); 
                        $this->depth--;  // 层数递减,返回父节点的end_handler,或者到同层兄弟节点的start_handler去。
                }
        }

 

 

上面的解说可能不适合初学者,比如xml_parse以及,json格式数组等等知识

不过都可以在www.php.net上找到资料

xml_parse相关: http://jp2.php.net/manual/en/function.xml-parse.php

json_encode相关: http://jp2.php.net/manual/en/function.json-encode.php

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值