Php 通过17gb xml文件进行解析/扫描

Php 通过17gb xml文件进行解析/扫描,php,xml,xml-parsing,Php,Xml,Xml Parsing,我正在尝试解析stackoverflow转储文件(Posts.xml-17gb)。它的格式如下: <posts> <row Id="15228715" PostTypeId="1" /> . <row Id="15228716" PostTypeId="2" ParentId="1600647" LastActivityDate="2013-03-05T16:13:24.897"/> </posts> . 我必须用他们的答案“分组”每个问题。

我正在尝试解析stackoverflow转储文件(Posts.xml-17gb)。它的格式如下:

<posts>
<row Id="15228715" PostTypeId="1" />
.
<row Id="15228716" PostTypeId="2" ParentId="1600647" LastActivityDate="2013-03-05T16:13:24.897"/>
</posts>

.
我必须用他们的答案“分组”每个问题。基本上,查找一个问题(posttypeid=1)使用另一行的parentId查找其答案并将其存储在db中

我尝试使用querypath(DOM)来实现这一点,但它一直在退出(139)。我猜是因为文件太大,我的电脑无法处理它,即使交换量很大

我考虑过xmlreader,但在我看来,使用xmlreader时,程序会大量读取文件(查找问题、寻找答案、重复很多次),因此是不可行的。我错了吗

还有其他方法吗

救命啊


这是一次解析

使用PHP xmlreader似乎是正确的做法

原因: 因为你的陈述:

我必须用他们的答案“分组”每个问题。基本上找到一个 问题(posttypeid=1)使用另一行的parentId查找其答案 并将其存储在数据库中

我的理解是,你喜欢建立一个包含问题和答案的数据库。因此,没有理由在XML级别进行“分组”。将所有相关信息放入数据库中,并在数据库级别上进行分组-使用DB命令(sql…)


您必须使用类似于“使用目标解析器方法”的东西,例如[Python中的高性能XML解析与(即使是针对Python,这也是一个良好的开端)。这在XMLReader中应该是可能的。

因为处理这个大文件的方式不是顺序的,而是需要直接访问,所以我认为唯一可行的选择是将数据加载到XML数据库中

我考虑过xmlreader,但在我看来,使用xmlreader时,程序会阅读文件很多次(找到问题,寻找答案,重复很多次),因此是不可行的。我错了吗

是的,您错了。使用XMLReader,您可以指定自己希望遍历文件的频率(通常只执行一次)。对于您的情况,我看不出有任何理由不能在每个
元素上都插入1:1。您可以根据要插入的数据库(表?)的属性来决定

我通常建议使用一组迭代器,使使用XMLReader进行遍历变得更容易。它被调用并允许在
XMLReader
上执行
foreach
,因此代码通常更容易读写:

$reader = new XMLReader();
$reader->open($xmlFile);

/* @var $users XMLReaderNode[] - iterate over all <post><row> elements */
$posts = new XMLElementIterator($reader, 'row');
foreach ($posts as $post)
{
    $isAnswerInsteadOfQuestion = (bool)$post->getAttribute('ParentId')

    $importer = $isAnswerInsteadOfQuestion 
                ? $importerAnswers 
                : $importerQuestions;

    $importer->importRowNode($post);
}
$reader=newXMLReader();
$reader->open($xmlFile);
/*@var$users XMLReaderNode[]-迭代所有元素*/
$posts=newXMLElementIterator($reader,'row');
foreach($posts作为$post)
{
$isAnswerInsteadOfQuestion=(bool)$post->getAttribute('ParentId')
$importer=$Isanswer代替问题
?$importerAnswers
:$importerQuestions;
$importer->importRowNode($post);
}
如果您关心顺序(例如,您可能担心某些父级答案在答案存在时不可用),我会在导入器层内,而不是在遍历中进行处理


根据这种情况是否经常发生,非常经常,从不或完全从不,我会使用不同的策略。例如,对于从不,我会在激活外键约束的情况下直接插入到数据库表中。如果经常发生,我会为整个导入创建一个插入事务,在该事务中,键约束被解除并在最后重新激活。

use
SimpleXMLIterator
取而代之的是….@Baba不太可能。请参阅。它将整个文件加载到内存中,然后对其进行迭代。XMLReader将迭代每个节点,而不会将整个文件加载到内存中,但除非您另有说明,否则它只会执行一次。有趣的是,必须将16 GB中的15 GB放入交换,然后从中读取。它将花几个小时。我会考虑通过文件,从一个标签到另一个标签,手动。我看不到任何其他方式来交换。同意。有时我认为人们忽略了最简单的解决方案。谢谢你的时间,你是对的,我错了。我成功地使用XMLRead解决了我的困境。我注意到了2件事:答案总是在问题之后(很明显),并且答案出现在接下来的几千行中(很少有例外),因此编写脚本来缓存几千个问题,查找它们的答案,将数组拼接一半并重复!再次感谢“PHP致命错误:找不到类'XMLElementIterator'”