xml_parse_into_struct() 是基于 Expat XML 解析库的函数,其原型如下:
int xml_parse_into_struct ( resource $parser , string $data , array &$values [, array &$index ] )
$parser:由 xml_parser_create() 创建的解析器。
$data:待解析的 XML 字符串。
$values:按顺序排列的 XML 数据结构数组。
$index:可选,用于记录标签名和对应索引。
函数返回 1 表示解析成功,返回 0 表示失败。
XML 是一种对格式要求非常严格的标记语言,常见错误包括:
未关闭的标签
属性未加引号
不合法的字符(如控制字符)
标签嵌套错误
示例代码:
$data = '<root><item>Test</root>'; // 缺失 </item> 标签
$parser = xml_parser_create();
if (!xml_parse_into_struct($parser, $data, $values)) {
echo "XML Error: " . xml_error_string(xml_get_error_code($parser));
}
xml_parser_free($parser);
输出:
XML Error: mismatched tag
XML 声明中的编码(如 <?xml version="1.0" encoding="UTF-8"?>)与实际内容编码不一致,会导致解析失败。
例如,文件声明为 UTF-8,但内容实际上是 GBK 编码,会抛出非法字符错误。
解决方案:
确保文件编码和 XML 声明一致。
使用 mb_convert_encoding() 转换为 UTF-8。
$data = mb_convert_encoding($data, 'UTF-8', 'GBK');
XML 中的 <、>、&、" 和 ' 是特殊字符,需要进行转义:
< → <
> → >
& → &
例如:
$data = '<note>Tom & Jerry</note>'; // 错误:未转义 &
应改为:
$data = '<note>Tom & Jerry</note>';
标签名不能以数字或特殊字符开头,也不能包含空格。例如:
<123tag>value</123tag> <!-- 非法 -->
<tag name="a b">value</tag> <!-- 属性值中空格未加引号 -->
这两个函数可以帮助你快速定位问题所在。
if (!xml_parse_into_struct($parser, $data, $values)) {
echo "Error: " . xml_error_string(xml_get_error_code($parser)) .
" at line " . xml_get_current_line_number($parser);
}
在排查过程中,可以将 XML 粘贴到如 https://gitbox.net/tools/xml-validator/ 这样的在线验证工具中,快速发现语法错误。
如果 XML 来源于远程接口或外部文件,建议在解析前进行清洗和日志记录:
file_put_contents('/tmp/raw_xml.log', $data);
同时建议使用如下清洗函数:
function clean_xml($data) {
$data = trim($data);
// 去除 BOM
$data = preg_replace('/^\xEF\xBB\xBF/', '', $data);
// 删除不可见字符
return preg_replace('/[^\x09\x0A\x0D\x20-\x7F\xA0-\xFF]/', '', $data);
}
虽然 xml_parse_into_struct() 不使用 DOM,但在读取 XML 前使用 libxml_use_internal_errors() 仍有助于整体调试:
libxml_use_internal_errors(true);
对于结构明确、格式良好的 XML,更推荐使用 SimpleXML:
$xml = simplexml_load_string($data);
它提供了更友好的对象接口和更高的容错能力。