簡體   English   中英

如何使用PHP順序解析大型XML文件

[英]How to use PHP to parse large XML file sequentially

我正在嘗試使用simpleXML在php中解析一個中等大小的XML文件(6mb)。 該腳本從XML文件中獲取每個記錄,檢查是否已將其導入,如果尚未導入,則將記錄中的更新/插入到我自己的數據庫中。

問題是我不斷收到關於超出內存分配的致命錯誤:

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 256 bytes) in /.../system/database/drivers/mysql/mysql_result.php on line 162

我通過使用以下行來增加最大內存分配來避免該錯誤(從此處開始提示):

ini_set('memory_limit', '-1');

但是,然后我以最大60秒的執行時間運行,無論出於何種原因,我的服務器(在Mac OS X上為XAMPP)都不允許我增加該時間(如果嘗試包含以下腳本,腳本將無法運行)像這樣的一行:

set_time_limit(240);

但是,這一切似乎都效率很低。 我是否應該能夠分解文件並按順序處理它? 在下面的控制器中,我有一個計數變量($ cycle)來跟蹤我正在進行的記錄,但是我無法弄清楚如何實現它,因為它仍然不必處理整個XML文件。

控制器(我正在使用CodeIgniter)具有以下基本結構:

    $f = base_url().'data/data.xml';
    if($data = file_get_contents($f))
    {
        $cycle = 0;
        $xml = new SimpleXMLElement($data);
        foreach($xml->person as $p)
        {

        //this makes a single call to db for single field based on id of record in XML file                
        if($this->_notImported('source',$p['id']))
            {
               //various process here, mainly breaking up the data for inserting into four different bales
            }
            $cycle++;
        }
    }

有什么想法嗎?

已編輯

為了進一步了解我在做什么,我獲取了每個元素和子元素的大多數屬性,並將其插入到數據庫中。 例如,使用我的舊代碼,我有類似以下內容:

$insert = array('indiv_name' => $p['fullname'],
                                    'indiv_first' => ($p['firstname']),
                                    'indiv_last' => ($p['lastname']),
                                    'indiv_middle' => ($p['middlename']),
                                    'indiv_other' => ($p['namemod']),
                                    'indiv_full_name' => $full_name,
                                    'indiv_title' => ($p['title']),
                                    'indiv_dob' => ($p['birthday']),
                                    'indiv_gender' => ($p['gender']),
                                    'indiv_religion' => ($p['religion']),
                                    'indiv_url' => ($url)
                                    );

有了使用XMLReader的建議(見下文),我如何完成對main元素和subelements的屬性的解析?

使用XMLReader

說您的文檔是這樣的:

<test>
   <hello>world</hello>
   <foo>bar</foo>
</test>

使用XMLReader:

$xml = new XMLReader;
$xml->open('doc.xml');

$xml->read();
while ($xml->read()) {
        if ($xml->nodeType == XMLReader::ELEMENT) {
                print $xml->name.': ';
        } else if ($xml->nodeType == XMLReader::TEXT) {
                print $xml->value.PHP_EOL;
        }
}

輸出:

hello: world
foo: bar

令人高興的是,您還可以使用expand將節點作為DOMNode對象獲取。

聽起來像是問題在於您在嘗試操縱整個xml文件之前將其讀入內存。 使用XMLReader逐步瀏覽文件流,而不是將所有內容都加載到內存中進行操作。

不使用xml,而是使用json呢? JSON格式的數據會小得多,因此我想您不會遇到相同的內存問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM