4

我正在尝试解析 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) 执行此操作,但它一直在 exiting(139) 。我的猜测是因为文件很大,我的电脑无法处理它,即使交换很大。

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

还有其他方法/方式吗?

帮助!

这是一次性解析。

4

3 回答 3

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

如果您担心顺序(例如,您可能担心某些答案父母的答案不可用,而答案是),我会在导入器层内小心,而不是在遍历内。

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

于 2013-06-03T09:15:41.797 回答
2

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

于 2013-06-02T13:22:21.127 回答
1

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

原因:因为您的陈述:

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

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

您必须使用类似“使用目标解析器方法”之类的东西,例如[使用xml在 Python 中进行高性能 XML 解析(即使是用于 Python,这也是一个好的开始)。这应该可以通过 XMLReader 实现。

于 2013-06-02T11:30:39.800 回答