我使用的SimpleXML加载一些XML文件(我没有写/提供并不能真正改变的格式)。
偶尔(例如,一个或两个文件每50左右),他们不逃避任何特殊字符(主要是及,但有时其他随机无效的东西太多)。 这将创建和问题,因为SimpleXML的用php,只不过没有了,我真的不知道来处理解析无效的XML什么好办法。
我的第一个想法是预处理XML作为一个字符串,并把所有的字段作为CDATA所以它会工作,但由于某种原因敬虔我需要处理XML把所有的数据在属性字段。 因此,我不能使用CDATA想法。 的XML之中的一个示例:
<Author v="By Someone & Someone" />
最新最好的方法来处理这个来代替从XML的所有无效字符之前,我在用SimpleXML加载它?
你需要的是一些将使用的libxml的内部错误定位无效字符,并相应地逃离他们。 下面是我怎么会写一个样机。 看看结果libxml_get_errors()
的错误信息。
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;
foreach (libxml_get_errors() as $error)
{
// $pos is the position of the faulty character,
// you have to compute it yourself
$pos = compute_position($error->line, $error->column);
$fixed_xml .= substr($xml, $last_pos, $pos - $last_pos) . htmlspecialchars($xml[$pos]);
$last_pos = $pos + 1;
}
$fixed_xml .= substr($xml, $last_pos);
libxml_use_internal_errors($use_internal_errors);
return simplexml_load_string($fixed_xml);
}
我认为workaroung创建compute_position功能将会使处理前的XML字符串持平。 重写发表乔什代码:
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
$xml = str_replace(array("\r\n", "\r", "\n"), "", $xml);
// get file encoding
$encoding = mb_detect_encoding($xml);
foreach (libxml_get_errors() as $error)
{
$pos = $error->column;
$invalid_char = mb_substr($xml, $pos, 1, $encoding);
$fixed_xml .= substr($xml, $last_pos, $pos - $last_pos) . htmlspecialchars($invalid_char);
$last_pos = $pos + 1;
}
$fixed_xml .= substr($xml, $last_pos);
libxml_use_internal_errors($use_internal_errors);
return simplexml_load_string($fixed_xml);
}
我已经添加了编码的东西becose我有问题,从字符串获得字符数组简单[指数]的方式。
这一切都应该工作,但是,不知道为什么,我已经看到了$错误 - >列给了我不同的数字比它应该。 试图通过简单的XML里面添加一些无效字符,并检查它会返回什么价值来调试这一点,但它没有运气。 希望有人能告诉我什么是错的这种做法。