2010-02-14 14 views
7

Ho bisogno di caricare un documento XML in PHP proveniente da una fonte esterna. L'XML non dichiara la codifica e contiene caratteri illegali come &. Se provo a caricare il documento XML direttamente nel browser ottengo errori come "È stato trovato un carattere non valido nel contenuto del testo" anche durante il caricamento del file in PHP ottengo molti avvisi come: xmlParseEntityRef: no name in Entity e Input is not proper UTF-8, indicate encoding ! Bytes: 0x9C 0x31 0x21 0x3C.Correggi l'XML malformato in PHP prima dell'elaborazione utilizzando le funzioni DOMDocument

È chiaro che l'XML non è ben formato e contiene caratteri non validi che devono essere convertiti in entità XML.

Questo perché il feed XML è composto da dati forniti da molti altri utenti e chiaramente non viene convalidato o riformattato prima di averlo ricevuto.

Ho parlato con il fornitore del feed XML e dicono che stanno cercando di convincere i fornitori di contenuti a risolverlo, ma questo sembra sciocco poiché dovrebbero prima convalidare l'input.

Fondamentalmente ho bisogno di correggere l'XML correggendo eventuali errori di codifica e convertendo qualsiasi carattere illegale in entità XML in modo che l'XML carichi il problema quando si usano le funzioni DOMDocument di PHP.

Il mio codice attualmente si presenta come:

$feedURL = '3704017_14022010_050004.xml'; 
    $dom = new DOMDocument(); 
    $dom->load($feedURL); 

file XML di esempio che mostra problema di codifica (clicca per scaricare): feed.xml

Esempio XML che contiene caratteri che non sono stati convertiti in entità XML:

<?xml version="1.0"?> 
<feed> 
<RECORD> 
<ID>117387</ID> 
<ADVERTISERNAME>Test</ADVERTISERNAME> 
<AID>10544740</AID> 
<NAME>This & This</NAME> 
<DESCRIPTION>For one day only this is > than this.</DESCRIPTION> 
</RECORD> 
</feed> 
+3

"Come fanno tutti gli altri clienti soddisfatti (?) A gestire i dati e perché sono l'unico ragazzo miserabile" - questa è una domanda che chiederei al fornitore. Puoi fornire un (esatto) esempio di documento? – VolkerK

+0

Mi stavo chiedendo anch'io.Ho parlato con loro e mi hanno detto che stanno avendo problemi di qualità dei dati e hanno detto ai fornitori di contenuti di risolverlo. Suppongo che gli altri clienti abbiano trovato un modo per correggere il feed XML prima di tentare di elaborarlo. Quindi la mia domanda. – Camsoft

+0

@VolkerK Ho caricato un sottoinsieme dell'intero documento XML come XML completo come oltre 42.000 righe. – Camsoft

risposta

8

Provare a utilizzare la libreria Tidy che può essere utilizzata per pulire male HTML e XML http://php.net/manual/en/book.tidy.php

Una soluzione PHP puro per correggere alcuni XML come questo:

<?xml version="1.0"?> 
<feed> 
<RECORD> 
<ID>117387</ID> 
<ADVERTISERNAME>Test < texter</ADVERTISERNAME> 
<AID>10544740</AID> 
<NAME>This & This</NAME> 
<DESCRIPTION>For one day only this is > than this.</DESCRIPTION> 
</RECORD> 
</feed> 

sarebbe qualcosa di simile a questo:

function cleanupXML($xml) { 
    $xmlOut = ''; 
    $inTag = false; 
    $xmlLen = strlen($xml); 
    for($i=0; $i < $xmlLen; ++$i) { 
     $char = $xml[$i]; 
     // $nextChar = $xml[$i+1]; 
     switch ($char) { 
     case '<': 
      if (!$inTag) { 
       // Seek forward for the next tag boundry 
       for($j = $i+1; $j < $xmlLen; ++$j) { 
       $nextChar = $xml[$j]; 
       switch($nextChar) { 
       case '<': // Means a < in text 
        $char = htmlentities($char); 
        break 2; 
       case '>': // Means we are in a tag 
        $inTag = true; 
        break 2; 
       } 
       } 
      } else { 
      $char = htmlentities($char); 
      } 
      break; 
     case '>': 
      if (!$inTag) { // No need to seek ahead here 
      $char = htmlentities($char); 
      } else { 
      $inTag = false; 
      } 
      break; 
     default: 
      if (!$inTag) { 
      $char = htmlentities($char); 
      } 
      break; 
     } 
     $xmlOut .= $char; 
    } 
    return $xmlOut; 
    } 

Che è una semplice macchina a stati notando se siamo in un tag o no e se no, quindi codifica il testo usando htmlentities.

Vale la pena notare che questo sarà affamato di memoria su file di grandi dimensioni, quindi si consiglia di riscriverlo come un plug-in di flusso o un pre-processore.

+0

Non sono riuscito a farlo funzionare con MAMP sul mio Mac. È davvero frustrante. – Camsoft

+0

Esiste una pura libreria PHP simile a Tidy chiamata htmLawed [http://www.bioinformatics.org/phplabware/internal_utilities/htmLawed/]. Potresti avere più fortuna con quello. – Neel

+0

Questo sembra interessante anche se sembra essere più sulla correzione degli errori XML. Gli errori reali che sto avendo hanno a che fare con la codifica mista del contenuto e dei caratteri che non sono stati convertiti in entità XML. – Camsoft

9

Per risolvere questo problema, impostare il DomDocument recover property-TRUE prima di caricamento del documento XML

$dom->recover = TRUE;

provare questo codice:

$feedURL = '3704017_14022010_050004.xml'; 
$dom = new DOMDocument(); 
$dom->recover = TRUE; 
$dom->load($feedURL); 
+0

Ha funzionato per me, grazie :) – Wiliam

+0

Funziona con "Contenuto aggiuntivo alla fine del documento in Entità" Avvertenze, vedere http://eval.in/26395 – hakre

Problemi correlati