快速版:
由于格式错误的文件(特别是未转义的字符),XMLReader抛出的标准(创新?任何?)方式是什么样的捕获和处理错误。使用Tidy(等等)进行预测并不是一个超级吸引人的选择,任何人都知道如何简单地跳过违规节点并向右移动?
描述性版本:
我们都知道,如果它没有正确形成它不是XML,但说实话 - 它发生了。客户端经常会输入需要读入mysql的大量(50-100MB +)xml文件。 XMLReader是显而易见的选择,我们编写了一个适合我们需求的包装器。
偶尔会发生错误并且read()无法杀死导入 - drat!它几乎总是一个没有逃脱的角色(前“&”),它将所有东西都绊倒。在大多数情况下,我们只是让客户端调用数据提供者并要求他们修复有缺陷的文件。不幸的是,数据提供者并不总是乐于和/或及时。如果我们能够简单地捕获错误并向右移动到下一个节点,那将是惊人的。
我花了很长时间试图阅读/破解这个,但找不到值得细读的东西。我错过了一些明显的东西吗
This SO question似乎很有希望,但它不会产生任何结果。通过1似乎应该要求读者恢复,但我们只是没有看到任何尝试/不同的错误消息等。这是相关的代码概述了方法:
$xml->open($file, null, LIBXML_NOERROR | LIBXML_NOWARNING | 1);
我总是可以用Tidy进行预处理,但必须有更好的方法。
我已经考虑了一些更“创造性”的方法,比如在当前节点的逻辑完成后用try / catch嗅探下一个Read(),但这似乎笨拙。看起来似乎有可能使用自定义/包装函数模拟Read(),这有助于在节点中移动并包含错误处理,但我有一种感觉,我过分简化了事情。
总而言之:当read()失败时,我怎样才能抓住错误并继续前进?我们有机会看到会发生什么错误(至少XMLReader会抛出的消息)?
$xml = new XMLReader();
$xml->open($file);
while ($xml->read()) {
}
答案 0 :(得分:2)
它是一个XML阅读器,它可以读取XML。无效的XML不是XML,不能用XML阅读器阅读 - 就像那样简单。
在导入之前在文件上运行xmllint
以查看它是否有效,或者执行正确的操作并告诉数据提供者生成有效的xml。
答案 1 :(得分:2)
关于问题的“查看错误”部分:
http://php.net/manual/en/function.libxml-use-internal-errors.php 如果此设置是默认的false值,则会在任何无效的XML上触发PHP警告。 换句话说,你应该看到它:p你只是没有注意,或者有一个设置或自定义错误处理程序,它隐藏了你的PHP警告。
如果使用true调用上述函数,则不会生成警告,而是会在此函数返回的内部数组中累积错误:
http://www.php.net/manual/en/function.libxml-get-errors.php
关于“移动”部分,我担心cweiske是对的,它无法完成。您可以使用某些工具预先筛选XML以查找错误(甚至使用XMLReader解析它们)并尝试更正找到的错误,即删除/替换无效字符,但是您需要重新启动对已更正数据的解析。
答案 2 :(得分:1)
我遇到了同样的问题。使用stream filter,您可以在将XML提供给XMLReader之前修复它。
这HTML to XML filter就是这么做的。将其用作
$dsn = "php://filter/read=htmltoxml.entities/resource=" . $url;
$xml = XMLReader::open($dsn);