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);
它提供了更友好的對象接口和更高的容錯能力。