PHP流式读取XML文件
之前在项目中有读取XML的需求,一开始采用的是simplexml将xml文件全部load到内存里,然后一个节点一个节点读的方式,后来随着XML文件的增大,内存被撑爆了。于是赶紧想办法,于是有了流式读取。一开始老大给了我一个封装XMLReader的类,但是我发现这个类不是很符合我的要求,于是又把XMLReader按我的要求重新封装了一遍,在此感谢老大moon。
目前我的类非常简单就提供几个方法,我提供了Demo供大家参考使用。话不多说上代码
<?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('xmlfile'); $im->setTagName("webName"); print_r($im->getData()); $im->setTagName("webSiteUrl"); print_r($im->getData()); $im->setTagName("app"); print_r($im->getData()); //$im->open('xmlfile'); $i = 0; while($i < 3 && $appinfo = $im->getData()){ print_r($appinfo); $i ++; } $im->close(); } } $d = new Demo(); $d->run();
目前够用了,以后继续改进吧,欢迎大家拍砖,一起进步完善。