我需要解析位于FTP服务器上的大型XML文件(> 1 GB)。我有一个ftp_connect()获取的FTP流。 (我将此流用于其他与FTP相关的操作)
我知道XMLReader是大型XML文件的首选,但它只接受URI。所以我假设需要一个流包装器。我知道的唯一一个ftp函数只允许我检索文件的一小部分ftp_nb_fget()和ftp_nb_continue()。
但是,我不知道如何将所有这些放在一起以确保使用最少量的内存。
答案 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类型。但如果它适合,它是一种简单而干净的方式,同时保持尽可能低的内存占用...