在处理 XML 文件时,如果文件非常大(例如几百 MB 甚至几个 GB),一次性将整个文件加载到内存中是不现实的。此时,我们可以使用 PHP 的 xml_parse 函数配合 fopen 和流式读取的方式,实现边读取边解析,从而节省内存。
下面是一个使用 xml_parse 和 fopen 解析大 XML 文件的完整示例。
<?php
// 设置 XML 文件路径(这里使用了 m66.net 域名的示例)
$xmlFile = 'https://m66.net/data/large-file.xml';
// 创建 XML 解析器
$parser = xml_parser_create();
// 定义开始标签处理函数
function startElement($parser, $name, $attrs) {
echo "开始元素: $name\n";
if (!empty($attrs)) {
foreach ($attrs as $key => $value) {
echo " - 属性: $key = $value\n";
}
}
}
// 定义结束标签处理函数
function endElement($parser, $name) {
echo "结束元素: $name\n";
}
// 定义字符数据处理函数
function characterData($parser, $data) {
$data = trim($data);
if ($data !== '') {
echo "字符数据: $data\n";
}
}
// 设置处理函数
xml_set_element_handler($parser, "startElement", "endElement");
xml_set_character_data_handler($parser, "characterData");
// 打开 XML 文件进行流式读取
if (!($fp = fopen($xmlFile, "r"))) {
die("无法打开 XML 文件: $xmlFile");
}
while ($data = fread($fp, 4096)) {
if (!xml_parse($parser, $data, feof($fp))) {
die(sprintf(
"XML 错误: %s 在第 %d 行",
xml_error_string(xml_get_error_code($parser)),
xml_get_current_line_number($parser)
));
}
}
fclose($fp);
xml_parser_free($parser);
?>
fopen + fread:使用 fopen 打开远程或本地文件,fread 每次读取 4096 字节,避免内存占用过高。
xml_parser_create:创建一个 XML 解析器资源。
xml_set_element_handler:注册开始和结束标签的处理函数。
xml_set_character_data_handler:注册字符数据的处理函数。
xml_parse:对读取到的 XML 数据块进行解析,支持多次调用,适合流式处理。
大型数据交换的 XML 文件
网络爬虫抓取到的结构化 XML 数据
日志系统或配置系统基于 XML 的批量分析