2009-07-19 15 views
63

Ho bisogno di analizzare alcuni file HTML, tuttavia, non sono ben formati e il PHP stampa gli avvisi. Voglio evitare questo comportamento di debug/avviso in modo programmatico. Si prega di avvisare. Grazie!Disabilita gli avvisi quando si carica HTML non ben formato da DomDocument (PHP)

Codice:

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

questo:

@$xmlDoc->loadHTML($fetchResult) 

possono sopprimere gli avvertimenti ma come faccio a catturare questi avvertimenti programatically?

+0

Prova questa soluzione - sembra essere molto più facile - http://stackoverflow.com/questions/6090667/php-domdocument-errors-warnings-on-html5-tags – Marcin

+0

Conversione di ingresso schifoso di uscita corretta è ciò che paga le fatture;) L'opzione [recuperare è nel manuale] (http://nl1.php.net/manual/en/class.domdocument.php#domdocument.props.recover). è solo un booleano. Puoi semplicemente chiamare '$ dom-> saveHTML()', quindi vedi che tipo se il documento libxml sta cercando di fare il tuo input '$ html', di solito è piuttosto vicino/ok. – Wrikken

risposta

16

È possibile installare un gestore di errore temporaneo con 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()); 
} 
+0

Grazie! Un trucco così bello! Il codice è semplice e pulito. – Viet

+7

Sembra molto eccessivo per la situazione. Nota le funzioni libxml2 di PHP. – thomasrutter

+0

Buon punto, Thomas. Non sapevo di queste funzioni quando ho scritto questa risposta. Se non sbaglio, fa la stessa cosa internamente. – troelskn

184

chiamata

libxml_use_internal_errors(true); 

prima della trasformazione con con $xmlDoc->loadHTML()

Questo dice agli errori e agli avvertimenti di libxml2 not to send attraverso PHP. Quindi, per verificare la presenza di errori e gestirli personalmente, puoi consultare libxml_get_last_error() e/o libxml_get_errors() quando sei pronto.

+17

@ Viet- questo dovrebbe * probabilmente * essere la risposta accettata ... – Ben

75

Per nascondere gli avvertimenti, si deve dare istruzioni speciali per libxml che viene utilizzato internamente per eseguire l'analisi:

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

Il libxml_use_internal_errors(true) indica che si sta andando a gestire gli errori e gli avvisi te stesso e non voglio che rovinino l'output del tuo script.

Questo non è lo stesso dell'operatore @. Gli avvisi vengono raccolti dietro le quinte e successivamente è possibile recuperarli utilizzando libxml_get_errors() nel caso in cui si desideri eseguire la registrazione o restituire l'elenco dei problemi al chiamante.

Se si utilizzano o meno gli avvisi raccolti, è necessario cancellare sempre la coda chiamando .

Preservare lo stato

Se si dispone di altro codice che utilizza libxml può essere utile per assicurarsi che il codice non altera il globale stato della gestione degli errori; per questo, è possibile utilizzare il valore di ritorno di libxml_use_internal_errors() per salvare lo stato precedente.

// 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

Devo usare libxml_use_internal_errors (false); quando fatto? – Greeso

+2

@Greeso: è impostato sul valore * precedente *. Ciò viene fatto dal concetto che potrebbe essere stato configurato per qualche altro codice globalmente diverso da 'FALSE' e impostandolo su' FALSE' in seguito distruggerà quell'impostazione. Usando il precedente valore di ritorno '$ libxml_previous_state' questi potenziali effetti collaterali sono prevenuti perché la configurazione originale è stata ripristinata in modo indipendente da questo luogo. L'impostazione 'libxml_use_internal_errors()' è globale, quindi vale la pena prendersi un po 'di attenzione. – hakre

+0

Se ci sono già errori libxml in sospeso, non li mangeresti? – cHao

Problemi correlati