PHP-如何使用php处理比较大的xml文件?
说下具体问题:
需要从别的网站抓取xml文件,比如用curl抓取然后处理。
目前碰到的问题是,抓取并处理时,由于xml文件比较大,因此会造成处理时间长、cpu占用高、内存占用多的问题。
该如何解决这3个问题呢?之前考虑分片处理xml,但是没有什么好的方案。
补充一下:需要考虑内存占用、CPU占用。由于服务器比较烂,目前我处理500k以上的xml,使用SimpleXML来做已经有点支撑不住了,所以才会考虑能不能对xml文件进行分段读取拆分解析。
附上一个xml文件供测试:
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
首先,XML一般用做配置文件,PHP处理大的XML配置文件相当慢,特别是用simplepathxml,当path一个结点很深时。我一般的做法是:直接在运行前期直接把XML转化成php数组文件的形式,然后在需要的时候直接require这个转化后的PHP数组文件。可以参考:
http://blog.csdn.net/zhangwu416826/article/details/7774148有我写好的代码。
先用SAX解析XML,然后用XMLReader循环读取
<?php
// Parsing a large document with XMLReader with Expand - DOM/DOMXpath
$reader = new XMLReader();
$reader->open("tooBig.xml");
while ($reader->read()) {
switch ($reader->nodeType) {
case (XMLREADER::ELEMENT):
if ($reader->localName == "entry") {
if ($reader->getAttribute("ID") == 5225) {
$node = $reader->expand();
$dom = new DomDocument();
$n = $dom->importNode($node,true);
$dom->appendChild($n);
$xp = new DomXpath($dom);
$res = $xp->query("/entry/title");
echo $res->item(0)->nodeValue;
}
}
}
}
参考:PHP XML Parsing
可以使用XMLReader 解析大型 XML 文件
<?php
$reader = new XMLReader();
$reader->open("tooBig.xml");
while ($reader->read()) {
switch ($reader->nodeType) {
case (XMLREADER::ELEMENT):
if ($reader->localName == "entry") {
if ($reader->getAttribute("ID") == 5225) {
while ($reader->read()) {
if ($reader->nodeType == XMLREADER::ELEMENT) {
if ($reader->localName == "title") {
$reader->read();
echo $reader->value;
break;
}
if ($reader->localName == "entry") {
break;
}
}
}
}
}
}
}
?>
这里还有其他一些可选的解决方案,参考一下:
http://www.ibm.com/developerworks/cn/xml/x-xmlphp2.html
这个感觉上是php的效率问题, c/c++解析xml的效率比较高, 可以考虑使用php调用c++程序来解析xml, 平时用的rapidxml速度很快,解析一个3.3万行,1.5M大小的xml,大约4ms左右
PHP中有两种主要的XML解析器
1)基于树的解析器。它是把整个文档存储为树的数据结构中,即需要把整个文档都加载到内存中才能工作。所以,当处理大型XML文档时候,性能剧减。SimpleXML和DOM扩展属于此类型解析器。
2)基于流的解析器。它不会一次把整个文档加载到内存中,而是每次分别读取其中的一个节点并允许实时与之交互(当移向下一个节点时,上一个节点是被丢弃,但也设置为保留)。很明显,其效率要高且占内存少,不便之处代码量大点。
所以,PHP中处理大型XML文档可以用XMLReader扩展方案(基于流的解析器)。它在PHP 5.1中默认是启用的。
以下是示例:
<?php
$xml_file = file_get_contents('http://www.meituan.com/api/v2/beijing/deals');
// 创建对象
$reader = new XMLReader();
// 从一个文档或URL中加载XML数据
$reader->open($xml_file);
// 遍历
while($reader->read()) {
// statement
}
?>