2009-07-19 4 views
63

Ich muss einige HTML-Dateien parsen, sie sind jedoch nicht gut formatiert und PHP gibt Warnungen aus. Ich möchte ein solches Debugging/Warnverhalten programmatisch vermeiden. Bitte beraten. Vielen Dank!Warnungen beim Laden von nicht gut formatiertem HTML von DomDocument (PHP) deaktivieren

Code:

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

Dieses:

@$xmlDoc->loadHTML($fetchResult) 

können die Warnungen unterdrücken, aber wie kann ich diese Warnungen programmatisch erfassen?

+0

diese Lösung Versuchen - viel einfacher zu sein scheint - http://stackoverflow.com/questions/6090667/php-domdocument-errors-warnings-on-html5-tags – Marcin

+0

Converting lausig Eingang korrekte Ausgabe ist, was bezahlt die Rechnungen;) Die [Wiederherstellen Option ist im Handbuch] (http://nl1.php.net/manual/en/class.domdocument.php#domdocument.props.recover). es ist nur ein Boolescher. Sie können einfach '$ dom-> saveHTML()' aufrufen, um zu sehen, welche Art, wenn das Dokument libxml versucht, Ihre $ html-Eingabe zu machen, normalerweise ziemlich nah/ok ist. – Wrikken

Antwort

16

Sie können einen temporären Fehlerhandler installieren mit 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; 
    } 
} 

Verbrauch:

// 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()); 
} 
+0

Danke! So ein netter Trick! Der Code ist einfach und sauber. – Viet

+7

Scheint wie viel Overkill für die Situation. Beachten Sie die libxml2-Funktionen von PHP. – thomasrutter

+0

Guter Punkt, Thomas. Ich wusste über diese Funktionen nicht, als ich diese Antwort schrieb. Wenn ich mich nicht irre, tut es das selbe innerlich übrigens. – troelskn

184

Anruf

libxml_use_internal_errors(true); 

vor der Verarbeitung mit mit $xmlDoc->loadHTML()

Dies teilt libxml2 not to send Fehler und Warnungen bis zu PHP. Um dann auf Fehler zu prüfen und sie selbst zu behandeln, können Sie libxml_get_last_error() und/oder libxml_get_errors() konsultieren, wenn Sie bereit sind.

+17

@ Viet- das sollte * wahrscheinlich * die akzeptierte Antwort sein ... – Ben

75

die Warnungen auszublenden, Sie spezielle Anweisungen zu libxml geben, die intern verwendet, um die Analyse auszuführen:

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

Die libxml_use_internal_errors(true) zeigt an, dass Sie die Fehler und Warnungen selbst zu behandeln gehst und du Ich will nicht, dass sie die Ausgabe deines Skripts durcheinander bringen.

Dies ist nicht dasselbe wie der Operator @. Die Warnungen werden hinter den Kulissen gesammelt und können anschließend unter Verwendung von libxml_get_errors() abgerufen werden, falls Sie die Protokollierung durchführen oder die Liste der Probleme an den Aufrufer zurücksenden möchten.

Unabhängig davon, ob Sie die gesammelten Warnungen verwenden, sollten Sie die Warteschlange immer durch Aufrufen von libxml_clear_errors() löschen.

den Zustand Erhaltung

Wenn Sie anderen Code, der libxml nutzt es sich lohnen kann Ihren Code, um sicherzustellen, das Handling globalen Zustand des Fehlers nicht verändert; Dazu können Sie den Rückgabewert libxml_use_internal_errors() verwenden, um den vorherigen Status zu speichern.

// 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); 
+1

Sollte ich libxml_use_internal_errors (false) verwenden; wenn fertig? – Greeso

+2

@Greeso: Es wird auf den * vorherigen * Wert gesetzt. Dies wurde durch das Konzept erreicht, dass es für irgendeinen anderen Code konfiguriert wurde, der sich global von "FALSE" unterscheidet und nach dem Setzen auf "FALSE" danach diese Einstellung zerstört. Durch die Verwendung des vorherigen Rückgabewerts '$ libxml_previous_state' werden diese potentiellen Nebenwirkungen verhindert, da die ursprüngliche Konfiguration unabhängig von diesem Ort wiederhergestellt wurde. Die Einstellung 'libxml_use_internal_errors()' ist global, es lohnt sich also, etwas Vorsicht walten zu lassen. – hakre

+0

Wenn bereits libxml-Fehler anstehen, werden sie nicht gegessen? – cHao