Fixieren Sie missgebildete XML in PHP vor der Verarbeitung mithilfe von Domdocument -Funktionen

StackOverflow https://stackoverflow.com/questions/2261530

  •  20-09-2019
  •  | 
  •  

Frage

Ich muss ein XML -Dokument in PHP laden, das von einer externen Quelle stammt. Der XML erklärt nicht, dass es sich um Codierung handelt und enthält illegale Charaktere wie &. Wenn ich versuche, das XML -Dokument direkt im Browser zu laden, erhalte ich Fehler wie "Ein ungültiges Zeichen wurde im Textinhalt gefunden". Auch wenn die Datei in PHP geladen wird, erhalte ich viele Warnungen wie: xmlParseEntityRef: no name in Entity und Input is not proper UTF-8, indicate encoding ! Bytes: 0x9C 0x31 0x21 0x3C.

Es ist klar, dass die XML nicht gut geformt ist und illegale Zeichen enthält, die in XML -Entitäten konvertiert werden sollten.

Dies liegt daran, dass der XML -Feed aus Daten besteht, die von vielen anderen Benutzern geliefert wurden und eindeutig nicht validiert oder neu formatiert wird, bevor ich sie bekomme.

Ich habe mit dem Lieferanten des XML -Feeds gesprochen und sie sagen, dass sie versuchen, die Inhaltsanbieter dazu zu bringen, dies zu klären, aber dies scheint albern, da sie zuerst die Eingabe validieren sollten.

Grundsätzlich muss ich die XML -Korrektur von Codierungsfehlern beheben und illegale Zeichen in XML -Entitäten konvertieren, sodass das XML -Problem bei der Verwendung von PHP -Domdocument -Funktionen Probleme lädt.

Mein Code sieht derzeit aus:

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

Beispiel XML -Datei mit Codierungsproblemen (klicken Sie zum Herunterladen): feed.xml

Beispiel XML, das Zeichen enthält, die nicht in XML -Entitäten konvertiert wurden:

<?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>
War es hilfreich?

Lösung

Versuchen Sie, die Tidy -Bibliothek zu verwenden, mit der schlechtes HTML und XML gereinigt werden könnenhttp://php.net/manual/en/book.tidy.php

Eine reine PHP -Lösung, um einige XML wie folgt zu beheben:

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

Wäre so etwas:

  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;
  }

Dies ist eine einfache Zustandsmaschine, die feststellt, ob wir uns in einem Tag befinden oder nicht, und wenn nicht, codieren Sie den Text mithilfe von HTMLEnten.

Es ist erwähnenswert, dass dies auf große Dateien hungrig sein wird, sodass Sie es möglicherweise als Stream-Plugin oder Pre-Processor neu schreiben möchten.

Andere Tipps

Um dieses Problem zu lösen, setzen Sie die Domdocument Recovering Eigenschaft zu TRUE Vor dem Laden des XML -Dokuments

$dom->recover = TRUE;

Probieren Sie diesen Code aus:

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

Wenn die ordentliche Erweiterung keine Option ist, können Sie dies in Betracht ziehen htmlpurifier.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top