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();
目前够用了,以后继续改进吧,欢迎大家拍砖,一起进步完善。

浙公网安备 33010602011771号