解析/扫描17gb xml文件

时间:2013-06-02 10:09:41

标签: 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>

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

我尝试使用querypath(DOM)执行此操作,但它一直在退出(139)。我的猜测是因为文件太大,我的电脑无法处理它,即使是巨大的交换。

我考虑过xmlreader,但正如我在使用xmlreader看到的那样,程序会在整个文件中读取很多次(找到问题,寻找答案,重复很多次),因此不可行。我错了吗?

还有其他方法/方法吗?

帮助!

这是一次解析。

3 个答案:

答案 0 :(得分:5)

  

我考虑过xmlreader,但正如我在使用xmlreader看到的那样,程序会在整个文件中读取很多次(找到问题,寻找答案,重复很多次),因此不可行。我错了吗?

是的,你错了。使用XMLReader,您可以指定自己想要遍历文件的频率(通常一次)。对于您的情况,我认为没有理由您甚至不能在每个<row>元素上插入1:1。您可以根据属性决定要插入哪个数据库(表?)。

我通常建议使用一组迭代器,这样可以更轻松地遍历XMLReader。它被称为XMLReaderIterator并允许 foreach 通过 XMLReader ,以便代码通常更易于阅读和写入:

$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);
}

如果您担心订单(例如,您可能担心某些答案在答案期间无法提供父答案),我会在导入层内部,而不是在遍历内部。

取决于这种情况经常发生,经常发生,从来没有或者从来没有使用过不同的策略。例如。 for never 我会直接插入到激活了外键约束的数据库表中。如果经常,我会为整个导入创建一个插入事务,其中关键约束被解除并在最后重新激活。

答案 1 :(得分:2)

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

答案 2 :(得分:1)

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

原因:  因为你的陈述:

  

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

据我所知,您希望建立一个带有问题答案的数据库。因此,没有理由在XML级别上进行“分组”。将所有相关信息放在数据库中,并使用db命令(sql ...)在数据库级别进行分组。

你需要的是使用类似“使用目标解析器方法”的东西E.g [使用xml在Python中进行高性能XML解析(即使它适用于Python,也是一个好的开始)。这应该可以使用XMLReader。