XMLReader (in Php) and Error Handling
快速版本:
捕获和处理XMLReader因文件格式错误(尤其是未转义的字符)而引发的错误的标准方法(创新吗?摆弄Tidy(等等)不是一个吸引人的选择,有人知道一种简单地跳过有问题的节点并继续前进的方法吗?
描述性版本:
我们都知道,如果格式不正确,它就不是XML,但是说实话,它确实会发生。客户端会定期提取大量(50-100MB +)的xml文件,这些文件需要读入mysql。 XMLReader是显而易见的选择,我们编写了一个包装程序,可以很好地满足我们的需求。
有时会发生错误,并且read()无法终止导入-drat!它几乎总是一个未转义的字符(例如"&"),使所有内容崩溃。在大多数情况下,我们只会让客户致电数据提供者,并要求他们修复其有缺陷的文件。不幸的是,数据提供者并不总是义务和/或及时的。如果我们可以简单地捕捉到错误并继续前进到下一个节点,那将是惊人的。
我花了很长时间尝试阅读/破解此书,但找不到值得细读的内容。我是否缺少明显的东西?
这样的问题似乎很有希望,但没有产生任何结果。传递1似乎应该要求Reader恢复,但是我们只是没有看到任何尝试/不同的错误消息等。这是概述此方法的相关代码:
1 | $xml->open($file, null, LIBXML_NOERROR | LIBXML_NOWARNING | 1); |
我总是可以使用Tidy进行预处理,但是必须有更好的方法。
我已经考虑过其他一些"创造性"的方法,例如在完成当前节点的逻辑后用try / catch嗅探下一个Read(),但这充其量似乎很笨拙。使用自定义/包装函数来模拟Read()似乎也有潜力,该函数可以帮助遍历节点并合并错误处理,但是我觉得我过于简化了。
综上所述:当read()失败时,如何捕捉错误并继续前进?我们是否有机会看到即将发生的错误(至少XMLReader会抛出该消息)?
1 2 3 4 5 6 | $xml = new XMLReader(); $xml->open($file); while ($xml->read()) { } |
它是XML读取器,是用来读取XML的。无效的XML不是XML,也不能用XML阅读器读取-就这么简单。
在导入之前对文件运行
关于问题的"查看错误"部分:
http://php.net/manual/zh/function.libxml-use-internal-errors.php
当此设置为默认的false值时,将在任何无效的XML上触发PHP警告。
换句话说,您应该已经看过它了:p您只是没有注意,或者实际上没有设置或自定义错误处理程序而向您隐藏PHP警告。
如果使用true调用上述函数,则不会生成警告,而是在该函数返回的内部数组中累积错误:
http://www.php.net/manual/zh/function.libxml-get-errors.php
关于"继续前进"部分,恐怕cweiske是正确的,并且无法完成。您可以使用某些工具(甚至可以使用XMLReader对其进行解析)来预先筛选XML中的错误,并尝试纠正发现的错误,即删除/替换无效字符,但是随后您需要重新启动对已纠正数据的解析。
我遇到了同样的问题。使用流过滤器,可以先将XML修复,然后再将其提供给XMLReader。
这个HTML到XML的过滤器可以做到这一点。用作
1 2 | $dsn ="php://filter/read=htmltoxml.entities/resource=" . $url; $xml = XMLReader::open($dsn); |