2013-02-17 10 views
6

Sono in procinto di scrivere un parser e sto cercando di fare una buona gestione degli errori con eccezioni.Ottenere XMLReader di PHP per non generare errori php nei documenti non validi

Il codice di esempio seguente:

<?php 
$xml = <<<XML 
<?xml version="1.0"?> 
<rootElem> 
XML; 

$reader = new XMLReader(); 
$reader->xml($xml, null, LIBXML_NOERROR | LIBXML_NOWARNING); 

$reader->read(); 

Emette:

PHP Warning: XMLReader::read(): An Error Occured while reading in /Users/evert/code/xml/errortest.php on line 11 
PHP Stack trace: 
PHP 1. {main}() /Users/evert/code/xml/errortest.php:0 
PHP 2. XMLReader->read() /Users/evert/code/xml/errortest.php:11 

L'aggiunta di:

libxml_use_internal_errors(true); 

ha alcun effetto.

Il mio obiettivo è controllare gli errori in seguito (con libxml_get_errors()) e generare un'eccezione. Sento l'unica soluzione è l'utilizzo dell'operatore di silenzio (@), ma questa sembra una cattiva idea ..

Nota che quando non supero i LIBXML costanti, né uso libxml_use_internal_errors, ottengo un errore diverso , come ad esempio:

PHP Warning: XMLReader::read(): /Users/evert/code/xml/:2: parser error : Extra content at the end of the document in /Users/evert/code/xml/errortest.php on line 11 

Questo suggerisce che la libreria libxml sottostante è infatti sopprimendo l'errore, ma all'interno XMLReader viene generato un errore comunque.

+0

Forse implementare 'try' e' catch' per tenere traccia degli errori? – Anne

+1

Tuttavia non sono eccezioni, sono errori PHP tradizionali. L'unico modo in cui potrei usare try..catch, è con 'set_error_handler', che vorrei evitare mentre sto scrivendo una libreria, e non voglio alterare lo stato globale. – Evert

risposta

4

Sembra che non v'è alcun modo per eliminare l'altro avvertimento che utilizzare @, in quanto fonte di php per read() ha le seguenti linee:

retval = xmlTextReaderRead(intern->ptr); 
if (retval == -1) { 
    php_error_docref(NULL TSRMLS_CC, E_WARNING, "An Error Occured while reading"); 
    RETURN_FALSE; 
} else { 
    RETURN_BOOL(retval); 
} 

Quindi, solo gli errori di analisi reali all'interno xmlTextReaderRead() vengono soppresse dal libxml_use_internal_errors(true); o le opzioni passate a XMLReader::xml().

+3

Molto sfortunato; Ho trovato le stesse linee e aperto un ticket per questo: https://bugs.php.net/bug.php?id=64230 – Evert

+0

Anche @ non sembra funzionare per me - ho provato mentre (@ $ x -> read()) {...} e ricevo ancora un messaggio di errore. –

3

Dalla mia comprensione XMLReader, per convalidare il documento, è necessario eseguire un passaggio completo per tutto il documento.

Quello che sto facendo è:

// Enable internal libxml errors 
libxml_use_internal_errors(true); 
$xml = new \XMLReader(); 
$xsd='myfile.xsd'; 
$xml->open('myfile.xml'); 
$xml->setSchema ($xsd); 

// Conduct full pass through document. The only reason is to force validation. 
while (@$xml->read()) { }; // empty loop 

if (count(libxml_get_errors())==0) { 
    echo "provided xml is well formed and xsd-valid"; 
    // Now you can start processing without @ as document was validated against xsd and is xml-wellformed 
} 
else 
    echo "provided xml is wrong and/or not xsd-valid. stopping"; 

Naturalmente si può verificare la presenza di errori all'interno del ciclo vuota e poi pausa subito dopo primo errore. Ho notato che XMLReader non fallisce completamente dopo il primo errore - continua e porta una serie di problemi che è utile. A volte potrebbe essere utile stampare tutti i problemi rilevati invece di interrompere l'elaborazione dopo il primo problema.

La mia più grande preoccupazione è ciò che per la funzione isValid esistono in XMLReader :) Penso che questo è in realtà una sorta di soluzione, ma funziona molto bene e la validazione prima della lavorazione fiammiferi 95% dei casi d'uso XMLReader in quanto viene utilizzato per i grandi elaborazione di collezioni xml.

Problemi correlati