在通过DomDocument(PHP)加载格式不正确的HTML时禁用警告


79

我需要解析一些HTML文件,但是它们的格式不正确,PHP向其输出警告。我想以编程方式避免这种调试/警告行为。请指教。谢谢!

码:

// create a DOM document and load the HTML data
$xmlDoc = new DomDocument;
// this dumps out the warnings
$xmlDoc->loadHTML($fetchResult);

这个:

@$xmlDoc->loadHTML($fetchResult)

可以禁止显示警告,但是如何以编程方式捕获这些警告?


尝试这种解决方案-似乎要容易得多- stackoverflow.com/questions/6090667/...
马辛

将糟糕的输入转换为适当的输出才是有效的;)恢复选项在手册中。这只是一个布尔值。您可以打电话给我$dom->saveHTML(),看看文件libxml试图使用哪种$html输入,通常非常接近/确定。
2013年

Answers:


13

您可以使用安装临时错误处理程序 set_error_handler

class ErrorTrap {
  protected $callback;
  protected $errors = array();
  function __construct($callback) {
    $this->callback = $callback;
  }
  function call() {
    $result = null;
    set_error_handler(array($this, 'onError'));
    try {
      $result = call_user_func_array($this->callback, func_get_args());
    } catch (Exception $ex) {
      restore_error_handler();        
      throw $ex;
    }
    restore_error_handler();
    return $result;
  }
  function onError($errno, $errstr, $errfile, $errline) {
    $this->errors[] = array($errno, $errstr, $errfile, $errline);
  }
  function ok() {
    return count($this->errors) === 0;
  }
  function errors() {
    return $this->errors;
  }
}

用法:

// create a DOM document and load the HTML data
$xmlDoc = new DomDocument();
$caller = new ErrorTrap(array($xmlDoc, 'loadHTML'));
// this doesn't dump out any warnings
$caller->call($fetchResult);
if (!$caller->ok()) {
  var_dump($caller->errors());
}

10
对于这种情况,似乎有些大材小用。注意PHP的libxml2函数。
thomasrutter

好点,托马斯。当我写这个答案时,我不知道这些功能。如果我没记错的话,它内部也会做同样的事情。
troelskn

1
在这种情况下,它具有相同的效果,尽管它是在不同的级别上完成的:使用上述解决方案,虽然生成了PHP错误,但是抑制了PHP错误,但是对于我来说,它们不会成为PHP错误。我个人认为,如果要做的事情涉及通过@或set_error_handler()抑制PHP错误,那么这是错误的方法。不过那只是我的意见。请注意,PHP错误和异常完全是另一回事-使用try {} catch(){}很好。
thomasrutter

2
我认为我已经看到了一些错误报告,这表明它libxml_use_internal_errors与php的错误处理程序挂钩。
troelskn

我希望人们将这个答案向下滚动到下面的更好答案。
thomasrutter


94

要隐藏警告,您必须提供libxml内部用于执行解析的特殊说明:

libxml_use_internal_errors(true);
$dom->loadHTML($html);
libxml_clear_errors();

libxml_use_internal_errors(true)表明你要处理的错误和警告自己,你不想让它们弄乱你的脚本的输出。

这与@操作员不同。警告会在后台收集,之后,您可以通过使用它们来检索它们libxml_get_errors(),以防您希望执行日志记录或将问题列表返回给呼叫者。

无论您是否使用收集到的警告,都应始终通过调用清除队列libxml_clear_errors()

保持状态

如果您有其他代码在使用libxml它,则可能有必要确保您的代码不会改变错误处理的全局状态。为此,您可以使用返回值libxml_use_internal_errors()保存以前的状态。

// modify state
$libxml_previous_state = libxml_use_internal_errors(true);
// parse
$dom->loadHTML($html);
// handle errors
libxml_clear_errors();
// restore
libxml_use_internal_errors($libxml_previous_state);

2
@Greeso:设置为先前的值。这是由以下概念完成的:可能已为全局上FALSE与其他代码不同的其他一些代码配置了该代码,FALSE然后将其设置为会破坏该设置。通过使用先前的返回值,$libxml_previous_state可以防止那些潜在的副作用,因为已经独立于此位置需要恢复了原始配置。该libxml_use_internal_errors()设置是全局设置,因此值得注意。
hakre

如果已经存在未解决的libxml错误,这不会吃掉它们吗?
cHao

@cHao认为您一开始是空白是不合理的吗?:)
杰克

@Ja͢ck:不。如果以前调用过libxml_use_internal_errors(true),则它可能正在等待处理出现的任何错误。
cHao

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.