我正在尝试解析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看到的那样,程序会在整个文件中读取很多次(找到问题,寻找答案,重复很多次),因此不可行。我错了吗?
还有其他方法/方法吗?
帮助!
这是一次解析。
答案 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。