2010-01-24 59 views
3

我有一个50MB的XML文件。我想将它转换为CSV文件,但我发现大多数方法耗尽了服务器内存。是否有一种使用XMLReader等流方法来完成此操作的好方法。转换大型XML文件,以CSV在PHP

+4

XML结构答案是肯定的。 (随意进行更详细的答案发布更多细节) – 2010-01-24 21:51:03

+0

有没有太多其他细节 - 我有一个XML文件,我希望把CSV格式,我有一堆算法的要做到这一点,但他们所有使用太多的内存。你有一个不会耗尽记忆的算法吗? – Brian 2010-01-24 21:59:45

+0

等等,Excel?你在原始文章中说过XML。如果是Excel,请执行文件>另存为...> CSV以获取CSV输出。 – MidnightLightning 2010-01-24 22:00:58

回答

4

你想使用XmlReader解析XML,因为它的工作原理是基于事件的解析器 - 如。它不会将所有内容加载到内存中,而是在通过输入文件前进时读取。

4

的基于外籍SAX风格的解析器是最节省空间的选项:

http://php.net/xml_parse

它将执行你的$ start_element_handler每当元素标签打开或关闭$ end_element_handler回调,而不是将整个文档保存在内存中。

但尽管如此,50 MB不是很多,也许你的供应商可以了限制。

php_value memory_limit 100M 

在.htaccess/httpd.conf中,或将其设置在php.ini中。

+0

该文件为50MB,但该进程使用远远多于50MB。我增加了相当多的内存限制,但它仍然不起作用 – Brian 2010-01-24 21:57:07

+0

尝试与这些回调xml_parse ..它将使用很少的内存 – jspcal 2010-01-24 22:01:48

0

您是否尝试过增加内存限制? ini_set('memory_limit', '256M')

(这是BTW一个非常坏的解决方案)

0

我不知道很多关于PHP API,但似乎这个类可以帮助你:​​3210

基本上你正在寻找基于解析器事件,像旧的SAX。这个解析器类型会触发一个事件,或类似的东西。它的内存效率很高,因为它不需要将整个文档加载到内存中。

0

如果XML文件非常简单,并且可以避免通过完整的XML解析器,并且可以逐行读取PHP并逐行导出,则可以节省整个文件在内存中一次。什么是XML结构?

1

迟到了......

<domains><domain><name>myname.com</name></domain></domains>

$url = "http://mysite.com/my.xml"; 
    $returnData = file_get_contents($url); 
    $xml = simplexml_load_file($url); 

    $csv = 'my.csv'; 
    $path = '/var/www/html/'; 

    $domain = $xml->domains->domain; 

     $fullpath = $path.$csv; 
     $fp = fopen($fullpath, 'w'); 

    foreach ($xml->domains->domain as $domain) { 

     fputcsv($fp, get_object_vars($domain),',','"'); 

    } 

    fclose($fp); 

     header('Content-Description: File Transfer'); 
      header('Content-Type: application/csv'); 
     header('Content-Disposition: attachment; filename='.basename($csv)); 
     header('Content-Transfer-Encoding: binary'); 
     header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); 
     header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); 
     header('Pragma: public'); 
     header('Content-Length: ' . filesize($fullpath)); 
     readfile($fullpath); 

    exit; 
    } 
}