之前在项目中有读取XML的需求,一开始采用的是simplexml将xml文件全部load到内存里,然后一个节点一个节点读的方式,后来随着XML文件的增大,内存被撑爆了。于是赶紧想办法,于是有了流式读取。一开始老大给了我一个封装XMLReader的类,但是我发现这个类不是很符合我的要求,于是又把XMLReader按我的要求重新封装了一遍,在此感谢老大moon。
目前我的类非常简单就提供几个方法,我提供了Demo供大家参考使用。话不多说上代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125 |
<?php /** * * @author gaoran * Another new parser for (X|HT)ML(stream version) * @version 1.0 2014-06-02 18:10:00 * 感谢我的老大moon,之前moon写了一个XMLParser的类,但是我觉得不是我想要的,于是自己重新封装了一遍,自我感觉简单,好用 */ class New_XMLParser extends
XMLReader{ private
$_tagName ; /** * 设置打开xml文件的路径 */ public
function open( $xml , $encoding =null, $option =null){ parent::open( $xml , $encoding , $option ); } /** * 设置要读取数据的节点名称 */ public
function setTagName( $tagName ){ $this ->_tagName = $tagName ; } /** * 每次读取一个节点数据,以数组格式返回 */ public
function getData(){ if (! $this ->_tagName){ return
false;} while ( $this ->read()){ $tagName
= $this ->name; if ( $this ->nodeType == XMLReader::ELEMENT && $this ->_tagName == $tagName ){ $dom
= new DOMDocument( ‘1.0‘ , ‘utf-8‘ ); $d
= $dom ->importNode( $this ->expand(), true); //$dom->appendChild($d); $appinfo
= $this ->domToArray( $d ); return
$appinfo ; } } return
false; } /** * * @param SimpleXMLElement|DOMDocument|DOMNode $obj SimpleXMLElement, DOMDocument or DOMNode instance * @return array Array representation of the XML structure. */ public
static function domToArray( $obj ) { if
( $obj instanceof DOMNode) { $obj
= simplexml_import_dom( $obj ); } $result
= array (); $namespaces
= array_merge ( array ( ‘‘
=> ‘‘ ), $obj ->getNamespaces(true)); self::_toArray( $obj , $result , ‘‘ , array_keys ( $namespaces )); return
$result ; } protected
static function _toArray( $xml , & $parentData , $ns , $namespaces ) { $data
= array (); foreach
( $namespaces
as $namespace ) { foreach
( $xml ->attributes( $namespace , true) as
$key => $value ) { if
(! empty ( $namespace )) { $key
= $namespace
. ‘:‘ . $key ; } $data [ ‘@‘
. $key ] = (string) $value ; } foreach
( $xml ->children( $namespace , true) as
$child ) { self::_toArray( $child , $data , $namespace , $namespaces ); } } $asString
= trim((string) $xml ); if
( empty ( $data )) { $data
= $asString ; } elseif
(! empty ( $asString )) { $data [ ‘@‘ ] = $asString ; } if
(! empty ( $ns )) { $ns
.= ‘:‘ ; } $name
= $ns . $xml ->getName(); if
(isset( $parentData [ $name ])) { if
(! is_array ( $parentData [ $name ]) || !isset( $parentData [ $name ][0])) { $parentData [ $name ] = array ( $parentData [ $name ]); } $parentData [ $name ][] = $data ; } else
{ $parentData [ $name ] = $data ; } } /* * 关闭XML流 */ public
function close(){ parent::close(); } } class
Demo{ public
function run(){ $im
= new New_XMLParser(); $im ->open( ‘yingyonghui‘ ); $im ->setTagName( "webName" ); print_r( $im ->getData()); $im ->setTagName( "webSiteUrl" ); print_r( $im ->getData()); $im ->setTagName( "app" ); print_r( $im ->getData()); //$im->open(‘yingyonghui‘); $i
= 0; while ( $i
< 3 && $appinfo
= $im ->getData()){ print_r( $appinfo ); $i
++; } $im ->close(); } } $d = new Demo(); $d ->run(); |
目前够用了,以后继续改进吧,欢迎大家拍砖,一起进步完善。
原文:http://www.cnblogs.com/xiongji/p/3764578.html