流在PHP中解析4 GB XML文件

时间:2013-08-29 18:36:14

标签: php xml xml-parsing large-files large-data

我正在尝试并需要一些帮助来执行以下操作:

我想使用PHP流解析大型XML文件(4 GB)。我不能使用简单的XML或DOM,因为它们将整个文件加载到内存中,所以我需要能够传输文件的东西。

我如何在PHP中执行此操作?

我要做的是浏览一系列<doc>元素。并将他们的一些孩子写入一个新的xml文件。

我试图解析的XML文件如下所示:

<feed>
    <doc>
        <title>Title of first doc is here</title>
        <url>URL is here</url>
        <abstract>Abstract is here...</abstract>
        <links>
            <sublink>Link is here</sublink>
            <sublink>Link is here</sublink>
            <sublink>Link is here</sublink>
            <sublink>Link is here</sublink>
            <sublink>Link is here</sublink>
       </link>
    </doc>
    <doc>
        <title>Title of second doc is here</title>
        <url>URL is here</url>
        <abstract>Abstract is here...</abstract>
        <links>
            <sublink>Link is here</sublink>
            <sublink>Link is here</sublink>
            <sublink>Link is here</sublink>
            <sublink>Link is here</sublink>
            <sublink>Link is here</sublink>
       </link>
    </doc>
</feed>

我正在尝试将每个<doc>元素的所有子元素复制到一个新的XML文件中,除了<links>元素及其子元素。

所以我希望新的XML文件看起来像:

<doc>
    <title>Title of first doc is here</title>
    <url>URL is here</url>
    <abstract>Abstract is here...</abstract>
</doc>
<doc>
    <title>Title of second doc is here</title>
    <url>URL is here</url>
    <abstract>Abstract is here...</abstract>
</doc>

我非常感谢流/流解析/流读取原始XML文件,然后将其部分内容写入PHP中的新XML文件。

2 个答案:

答案 0 :(得分:4)

这是一次大学尝试。这假设正在使用文件,并且您要写入文件:

<?php

$interestingNodes = array('title','url','abstract');
$xmlObject = new XMLReader();
$xmlObject->open('bigolfile.xml');

$xmlOutput = new XMLWriter();
$xmlOutput->openURI('destfile.xml');
$xmlOutput->setIndent(true);
$xmlOutput->setIndentString("   ");
$xmlOutput->startDocument('1.0', 'UTF-8');

while($xmlObject->read()){
    if($xmlObject->name == 'doc'){
        $xmlOutput->startElement('doc');
        $xmlObject->readInnerXML();
        if(array_search($xmlObject->name, $interestingNodes)){
             $xmlOutput->startElement($xmlObject->name);
             $xmlOutput->text($xmlObject->value);
             $xmlOutput->endElement(); //close the current node
        }
        $xmlOutput->endElement(); //close the doc node
    }
}

$xmlObject->close();
$xmlOutput->endDocument();
$xmlOutput->flush();

?>

答案 1 :(得分:1)

对于这种情况,你不能使用DOM解析器,正如你所说的,由于文件大小,它不适合内存,即使你可以,它会很慢,因为它首先加载整个文件,之后你必须遍历它,所以,对于这种情况你应该尝试一个SAX解析器(面向事件/流),为那些你感兴趣的标签添加一个处理程序(doc,{{1 }},titleurl)并为每个事件添加新XML文件中的节点。

您可以在这里获得更多信息:

What is the fastest XML parser in PHP?

以下是代码内容的未经测试的示例:

abstract