45 Stimmen

Generierung von XML-Dokument in PHP (Sonderzeichen entkommen)

Ich erstelle ein XML-Dokument aus einem PHP-Skript und muss die XML-Sonderzeichen escapen. Ich kenne die Liste der Zeichen, die escaped werden sollten; aber wie mache ich das korrekt?

Sollen die Zeichen einfach nur mit einem Backslash (\) escaped werden oder was ist der richtige Weg? Gibt es eine eingebaute PHP-Funktion, die das für mich erledigen kann?

0 Stimmen

@Tchalvak: Du liegst bei vielen Punkten, die du in deiner Beschreibung kritisierst, falsch. Ich habe versucht, dies mit den vorhandenen Antworten sichtbar zu machen, hoffe das ist hilfreich.

0 Stimmen

Ich habe in meiner Antwort nicht vorgeschlagen, die DOM-API nur für die Zeichenfolgenmaskierung zu verwenden. Ich schlug vor, dein gesamtes XML-Dokument mit dieser API zu generieren. Dies ist eine Antwort auf die Probleme, die du in deiner Beschreibung des bountys erwähnst.

38voto

Tomas Jancik Punkte 1491

Ich habe eine einfache Funktion erstellt, die mit den fünf "vordefinierten Entitäten" umgeht, die in XML enthalten sind:

function xml_entities($string) {
    return strtr(
        $string, 
        array(
            "<" => "<",
            ">" => ">",
            '"' => """,
            "'" => "'",
            "&" => "&",
        )
    );
}

Verwendungsbeispiel Demo:

$text = "Test &  and encode  :)";
echo xml_entities($text);

Ausgabe:

Test &amp; <b> and encode </b> :)

Ein ähnlicher Effekt kann durch Verwendung von str_replace erzielt werden, aber es ist anfällig für doppelte Ersetzungen (nicht getestet, nicht empfohlen):

function xml_entities($string) {
    return str_replace(
        array("&",     "<",    ">",    '"',      "'"),
        array("&", "<", ">", """, "'"), 
        $string
    );
}

11 Stimmen

Du musst die Array-Elemente "&" und "&" an den Anfang verschieben, sonst werden alle anderen erstellten Entitäten ebenfalls ihre kaufmännischen Und-Zeichen ersetzt bekommen. Außerdem scheint die strtr Lösung überhaupt nicht zu funktionieren.

1 Stimmen

Für den OP, der seine eigene Frage beantwortet, gab es wirklich schwerwiegende Mängel hier. Ich habe versucht, es zum Guten zu bearbeiten, aber ich frage mich, ob der Originalcode verwendet wurde oder nicht ;) - @Nicky De Maeyer: Ja, es gibt fünf vordefinierte Entitäten in XML, ich habe einen Link platziert.

1 Stimmen

Ja, aber Attribut-Escaping ist anders als Element-Escaping (d. h. der Inhalt, den Sie in ein Attribut einfügen). Sehen Sie meinen Java-Code als Beispiel. Du willst nicht das tun, was @TomasJancik tut. Bitte nicht!. Verwenden Sie eine Bibliothek oder machen Sie es richtig.

35voto

Ionuț G. Stan Punkte 168218

Verwenden Sie die DOM-Klassen, um Ihr gesamtes XML-Dokument zu generieren. Es kümmert sich um Codierungen und Dekodierungen, um die wir uns nicht einmal kümmern wollen.


Bearbeitung: Dies wurde von @Tchalvak kritisiert:

Das DOM-Objekt erstellt ein vollständiges XML-Dokument, es lässt sich nicht so einfach darauf beschränken, nur einen String zu codieren.

Was falsch ist, DOMDocument kann problemlos nur ein Fragment richtig ausgeben:

$doc->saveXML($fragment);

was folgendes ergibt:

Test &  and encode  :)
Test &amp; <b> and encode </b> :)

wie folgt:

$doc = new DOMDocument();
$fragment = $doc->createDocumentFragment();

// XML wörtlich hinzufügen:
$xml = "Test &  and encode  :)\n";
$fragment->appendXML($xml);

// Text hinzufügen:
$text = $xml;
$fragment->appendChild($doc->createTextNode($text));

// das Ergebnis ausgeben
echo $doc->saveXML($fragment);

Siehe Demo

5 Stimmen

Laut bugs.php.net/bug.php?id=31191 möchten Sie speziell die createTextNode-Funktion verwenden, um eine ordnungsgemäße automatische Escapen zu erhalten.

0 Stimmen

Ich denke, das Problem von @Tchalvak ist, dass es nicht streambasiert ist. Das heißt, die Verwendung von DOM wird eine Menge Objekte erstellen. Wie ich in meiner Antwort erwähnt habe, kann er XMLWriter verwenden oder einfach meinen Java-Code nach PHP portieren, der das richtige Escaping durchführt (Tomas Janciks Methode ist nicht korrekt).

0 Stimmen

Hoppla, eval.in/10980 ist die korrekte Implementierung einer xmlentities()-Funktion, die die native Verarbeitung verwendet. Wahrscheinlich hat sie etwas Overhead, aber es ist wahrscheinlich die Ruhe des Geistes wert, eine native/zukunftssichere Funktionalität zu verwenden.

21voto

MarcDefiant Punkte 6301

Was ist mit der htmlspecialchars() Funktion?

htmlspecialchars($input, ENT_QUOTES | ENT_XML1, $encoding);

Hinweis: das ENT_XML1 Flag ist nur verfügbar, wenn Sie PHP 5.4.0 oder höher haben.

htmlspecialchars() mit diesen Parametern ersetzt die folgenden Zeichen:

  • & (kaufmännisches Und) wird zu &
  • " (Anführungszeichen) wird zu "
  • ' (Einfache Anführungszeichen) wird zu '
  • < (kleiner als) wird zu <
  • > (größer als) wird zu >

Sie können die Übersetzungstabelle mit der get_html_translation_table() Funktion erhalten.

1 Stimmen

Es besteht kein spezieller Bedarf, ENT_XML1 für XML-kompatible Kodierung zu verwenden - zumindest nicht für PHP-Versionen 4.3.0 bis 5.5.0alpha4. Auch htmlspecialchars($input, ENT_QUOTES, $encoding); funktioniert gut, wenn Sie mit einer numerischen anstelle einer benannten Entität leben können.

0 Stimmen

Das ist der beste Weg.

15voto

Josh Sunderman Punkte 151

Habe versucht, das Problem mit XML-Entitäten zu lösen, auf diese Weise gelöst:

htmlspecialchars($Wert, ENT_QUOTES, 'UTF-8')

0 Stimmen

Dies funktioniert nur, wenn diese Entitäten in XML definiert sind, siehe w3.org/TR/xml-entity-names

1voto

Adam Gent Punkte 45977

Richtige Escapen ist der richtige Weg, um korrekte XML-Ausgabe zu erzielen, aber Sie müssen das Escapen unterschiedlich für Attribute und Elemente behandeln. (Das ist Tomas' Antwort ist falsch).

Ich habe / gestohlen vor einer Weile Java-Code geschrieben, der zwischen Attribut- und Element-Escapen unterscheidet. Der Grund dafür ist, dass der XML-Parser jede Leerstelle insbesondere in Attributen als speziell betrachtet.

Es sollte trivial sein, das auf PHP zu portieren (Sie können Tomas Janciks Ansatz mit dem obigen entsprechenden Escapen verwenden). Sie müssen sich keine Sorgen um das Escapen erweiterter Entitäten machen, wenn Sie UTF-8 verwenden.

Wenn Sie meinen Java-Code nicht portieren möchten, können Sie sich XMLWriter anschauen, das strombasiert ist und libxml verwendet, sodass es sehr effizient sein sollte.

0 Stimmen

+1, denn ich hatte keine Ahnung, dass XMLWriter dies automatisch für dich macht.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X