【问题标题】:Disable warnings when loading non-well-formed HTML by DomDocument (PHP)通过 DomDocument (PHP) 加载格式不正确的 HTML 时禁用警告
【发布时间】:2010-11-12 01:05:41
【问题描述】:

我需要解析一些 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)

可以抑制警告,但如何以编程方式捕获这些警告?

【问题讨论】:

标签: php html warnings domdocument


【解决方案1】:

打电话

libxml_use_internal_errors(true);

在使用$xmlDoc->loadHTML()处理之前

这会将 libxml2 not to send 错误和警告告知 PHP。然后,要检查错误并自行处理,您可以在准备好后咨询libxml_get_last_error() 和/或libxml_get_errors()

libxml_use_internal_errors(true);
$dom->loadHTML($html);
$errors = libxml_get_errors();
foreach ($errors as $error) {
    // handle the errors as you wish
}

【讨论】:

  • 像接受的答案那样添加 20 行代码要容易得多。谢谢!
【解决方案2】:

要隐藏警告,您必须向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);

【讨论】:

  • @Greeso:设置为 previous 值。这是通过以下概念完成的,即它可能已针对与FALSE 全局不同的其他代码进行了配置,然后将其设置为FALSE 会破坏该设置。通过使用先前的返回值$libxml_previous_state,可以防止这些潜在的副作用,因为原始配置已独立于该位置的需要而恢复。 libxml_use_internal_errors() 设置是全局的,因此需要注意。
  • 如果已经有 libxml 错误未决,这不会吃掉它们吗?
  • @cHao 假设您从一张白纸开始是不是很合理? :)
  • @Ja͢ck:不。如果以前称为libxml_use_internal_errors(true),那么它可能正在等待处理出现的任何错误。
【解决方案3】:

设置选项“LIBXML_NOWARNING”和“LIBXML_NOERROR”也可以正常工作:

$dom->loadHTML($html, LIBXML_NOWARNING | LIBXML_NOERROR);

【讨论】:

    【解决方案4】:

    您可以使用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());
    }
    

    【讨论】:

    • 对于这种情况似乎有些矫枉过正。注意 PHP 的 libxml2 函数。
    • 好点,托马斯。当我写这个答案时,我不知道这些功能。如果我没记错的话,顺便说一句,它在内部做同样的事情。
    • 在这种情况下它具有相同的效果是的,虽然它是在不同的级别上完成的:使用上述解决方案,PHP 错误会生成但被抑制,但对于我的,它们不会成为 PHP 错误。我个人觉得,如果做某事涉及通过 @ 或 set_error_handler() 抑制 PHP 错误,那么这是错误的做法。这只是我的意见。请注意,PHP 错误和异常完全不同 - 使用 try {} catch() {} 很好。
    • 我想我已经看到了一些错误报告,这表明 libxml_use_internal_errors 挂钩到 php 的错误处理程序。
    • 我希望人们从这个答案向下滚动到下面更好的答案。
    猜你喜欢
    • 1970-01-01
    • 2011-02-06
    • 1970-01-01
    • 2014-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多