通过FTP解析大型XML文件

时间:2011-03-15 20:30:30

标签: php

我需要解析位于FTP服务器上的大型XML文件(> 1 GB)。我有一个ftp_connect()获取的FTP流。 (我将此流用于其他与FTP相关的操作)

我知道XMLReader是大型XML文件的首选,但它只接受URI。所以我假设需要一个流包装器。我知道的唯一一个ftp函数只允许我检索文件的一小部分ftp_nb_fget()和ftp_nb_continue()。

但是,我不知道如何将所有这些放在一起以确保使用最少量的内存。

3 个答案:

答案 0 :(得分:0)

嗯,我从未尝试使用FTP,但设置流上下文可以用

完成

然后只需在open()中输入FTP URI。

编辑:请注意,您也可以将Stream Context用于其他操作。如果要上传文件,则可以将相同的流上下文与file_put_contents结合使用,因此根本不需要任何ftp *函数。

答案 1 :(得分:0)

看起来您可能需要build on top of the low-level XML parser bits

特别是,在使用回调函数调用各种xml_set_*函数来处理元素,字符数据,命名空间,实体之后,您可以使用xml_parse一次处理XML的一个XML字符串块,等等。只要解析器检测到它有足够的数据就会触发这些回调, 意味着您可以在从FTP站点以任意大小的块读取文件时处理该文件。


使用CLI和xml_set_default_handler的概念证明,将为没有特定处理程序的所有内容调用:

php > $p = xml_parser_create('utf-8');
php > xml_set_default_handler($p, function() { print_r(func_get_args()); });
php > xml_parse($p, '<a');
php > xml_parse($p, '>');
php > xml_parse($p, 'Foo<b>Bar</b>Baz');
Array
(
    [0] => Resource id #3
    [1] => <a>
)
Array
(
    [0] => Resource id #3
    [1] => Foo
)
Array
(
    [0] => Resource id #3
    [1] => <b>
)
Array
(
    [0] => Resource id #3
    [1] => Bar
)
Array
(
    [0] => Resource id #3
    [1] => </b>
)
php > xml_parse($p, '</a>');
Array
(
    [0] => Resource id #3
    [1] => Baz
)
Array
(
    [0] => Resource id #3
    [1] => </a>
)
php >

答案 2 :(得分:0)

这取决于XML文件的架构。但是,如果它与RSS类似,它实际上只是一个很长的项目列表(全部封装在标签中),那么我所做的就是解析各个部分,并将它们解析为单独的domdocuments:

$buffer = '';
while ($line = getLineFromFtp()) {
    $buffer .= $line;
    if (strpos($line, '</item>') !== false) {
        parseBuffer($buffer);
        $buffer = '';
    }
}

这是伪代码,但它是处理特定类型的XML文件而不构建自己的XMLReader的一种轻松方式。您当然也需要检查开始标记,以确保缓冲区始终是有效的xml文件。

请注意,这不适用于所有XML类型。但如果它适合,它是一种简单而干净的方式,同时保持尽可能低的内存占用...