尽管这个问题已经存在10年了(当我打字时),我仍然遇到类似的XML解析问题(PHP8.1),这就是为什么我来到这里的原因。已经给出的答案很有帮助,但要么不完整,要么不一致,或者对我的问题和原始发帖人也不适用。
检查内部XML解析问题似乎是正确的,但是有735个错误代码(参见https://gnome.pages.gitlab.gnome.org/libxml2/devhelp/libxml2-xmlerror.html),因此需要更具适应性的解决方案。
我在上面使用了“不一致”一词,因为其他答案中最好的答案(@Adam Szmyd)将多字节字符串处理与非多字节字符串处理混合在一起。
以下代码以Adam的代码为基础,我为我的情况重新制定了它,我感觉可以根据实际遇到的问题进一步扩展。因此,我也不完全 - 抱歉!
这段代码的核心是将每个(在我的实现中只有1个)XML解析错误作为单独的情况进行处理。我遇到的错误是一个无法识别的HTML实体(ç - ç),所以我使用PHP实体替换来解决它。
function load_invalid_xml($xml)
{
$use_internal_errors = libxml_use_internal_errors(true);
libxml_clear_errors(true);
$sxe = simplexml_load_string($xml);
if ($sxe)
return $sxe;
$fixed_xml = '';
$last_pos = 0;
// make string flat
$xmlFlat = mb_ereg_replace( '(\r\n|\r|\n)', '', $xml );
// Regenerate the error but using the flattened source so error offsets are directly relevant
libxml_clear_errors();
$xml_doc = @simplexml_load_string( $xmlFlat );
foreach (libxml_get_errors() as $error)
{
$pos = $error->column - 1; // ->column appears to be 1 based, not 0 based
switch( $error->code ) {
case 26: // error undeclared entity
case 27: // warning undeclared entity
if ($pos >= 0) { // the PHP docs suggest this not always set (in which case ->column is == 0)
$left = mb_substr( $xmlFlat, 0, $pos );
$amp = mb_strrpos( $left, '&' );
if ($amp !== false) {
$entity = mb_substr( $left, $amp );
$fixed_xml .= mb_substr( $xmlFlat, $last_pos, $amp - $last_pos )
. html_entity_decode( $entity );
$last_pos = $pos;
}
}
break;
default:
}
}
$fixed_xml .= mb_substr($xml, $last_pos);
libxml_use_internal_errors($use_internal_errors);
return simplexml_load_string($fixed_xml);
}
&
这个符号,您在加载之前不可以转义它吗? - Dormilich