Asked  7 Months ago    Answers:  5   Viewed   42 times

I need to parse some HTML files, however, they are not well-formed and PHP prints out warnings to. I want to avoid such debugging/warning behavior programatically. Please advise. Thank you!

Code:

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

This:

@$xmlDoc->loadHTML($fetchResult)

can suppress the warnings but how can I capture those warnings programatically?

 Answers

69

You can install a temporary error handler with 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;
  }
}

Usage:

// 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());
}
Wednesday, March 31, 2021
 
Precastic
answered 7 Months ago
34

You need to have a look at $aum as it probably can't be formatted as a number.

Pop

echo $aum;
echo floatval($aum);

Before the error to see what you get. You might need to change the position you're looking at if you're picking up leading or trailing data.

Friday, May 28, 2021
 
Kenny
answered 5 Months ago
14

This is a bug in the symfony/var-dumper package when using PHP7.1. It was fixed in version 2.7.16, 2.8.9, 3.0.9 and 3.1.3. See the pull request: https://github.com/symfony/symfony/pull/19379

In my case, I needed to composer update my laravel framework packages, as my vendor directory copy of that package was at 2.7.9. (I'm using Laravel 5.1; later versions use 2.8 and 3.0 of symfony, which also had the bug)

Saturday, May 29, 2021
 
leebriggs
answered 5 Months ago
83
$doc = new DOMDocument();
$doc ->loadHTML("$html");
$tables = $doc->getElementsByTagName('table');
$table = $tables->item(0);//takes the first table in dom

foreach ($table->childNodes as $td) {
  if ($td->nodeName == 'td') {
    echo $td->nodeValue, "n";
  }
}
Saturday, May 29, 2021
 
superhero
answered 5 Months ago
24

This is mentioned in a couple of comments on the DomNode::removeChild documentation, with the issue apparently being how the iterator pointer on the foreach not being able to deal with the fact that you are removing items from a parent array while looping through the list of children (or something).

The recommended fix is to loop through the main node first and push the child nodes you want to delete to its own array, then loop through that "to-be-deleted" array and deleting those children from their parent. Example:

$dom = new DOMDocument();
@$dom->loadHTML($description);
$pTag = $dom->getElementsByTagName('p');

$spotid_children = array();

foreach ($pTag as $value) {
    /** @var DOMElement $value */
    $id = $value->getAttribute('data-spotid');
    if ($id) {
        $spotid_children[] = $value; 
    }
}

foreach ($spotid_children as $spotid_child) {
    $spotid_child->parentNode->removeChild($spotid_child); 
}
Monday, August 16, 2021
 
Litty
answered 3 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :