之前在项目中有读取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