wake-up-neo.com

Wie machen Sie Strings "XML Safe"?

Ich antworte auf einen AJAX - Aufruf, indem ich ein XML-Dokument über PHP -Echos sende. Um dieses XML-Dokument zu erstellen, durchlaufe ich die Datensätze einer Datenbank. Das Problem ist, dass die Datenbank Datensätze enthält, die '<' Symbole enthalten. Natürlich wirft der Browser an dieser Stelle einen Fehler ab. Wie kann das behoben werden?

55
JayD3e

Indem Sie diese Zeichen entweder mit htmlspecialchars umgehen, oder, besser geeignet, eine Bibliothek zum Erstellen von XML-Dokumenten verwenden, z. B. DOMDocument oder XMLWriter .

Eine andere Alternative wäre die Verwendung von CDATA-Abschnitten, aber dann müsste nach Vorkommen von ]]> gesucht werden.

Berücksichtigen Sie auch, dass Sie die für das XML-Dokument definierte Kodierung einhalten müssen (standardmäßig UTF-8).

61
Artefacto

Seit PHP 5.4 können Sie Folgendes verwenden:

htmlspecialchars($string, ENT_XML1);

Sie sollten die Kodierung wie folgt angeben:

htmlspecialchars($string, ENT_XML1, 'UTF-8');

Aktualisieren

Beachten Sie, dass das Obige nur konvertiert:

  • & bis &amp;
  • < bis &lt;
  • > bis &gt;

Wenn Sie Text für die Verwendung in einem Attribut in doppelte Anführungszeichen setzen möchten:

htmlspecialchars($string, ENT_XML1 | ENT_COMPAT, 'UTF-8');

konvertiert " in &quot; zusätzlich zu &, < und >.


Und wenn Ihre Attribute in einfachen Anführungszeichen stehen:

htmlspecialchars($string, ENT_XML1 | ENT_QUOTES, 'UTF-8');

konvertiert ' in &apos; zusätzlich zu &, <, > und ".

(Natürlich können Sie dies auch außerhalb von Attributen verwenden).


Siehe den manuellen Eintrag für htmlspecialchars .

57
user3409662

1) Sie können Ihren Text wie folgt als CDATA umbrechen:

<mytag>
    <![CDATA[Your text goes here. Btw: 5<6 and 6>5]]>
</mytag>

siehe http://www.w3schools.com/xml/xml_cdata.asp

2) Wie schon jemand gesagt hat: Entkomme den Zeichen. Z.B. wie so: 

5&lt;6 and 6&gt;5
9
Elvith

Versuche dies:

$str = htmlentities($str,ENT_QUOTES,'UTF-8');

Nachdem Sie Ihre Daten mit der Funktion htmlentities() gefiltert haben, können Sie die Daten im XML-Tag wie folgt verwenden: 

<mytag>$str</mytag>
5
Mosiur

Wenn überhaupt möglich, ist es immer eine gute Idee, XML anhand der XML-Klassen zu erstellen, anstatt Zeichenfolgen zu ändern. Dies hat den Vorteil, dass die Klassen Zeichen bei Bedarf automatisch mit Escapezeichen versehen.

5
Ed Schembor

Dies hinzuzufügen, falls es jemandem hilft.

Da ich mit japanischen Zeichen arbeite, wurde auch die Kodierung entsprechend festgelegt. Ich finde jedoch von Zeit zu Zeit, dass htmlentities und htmlspecialchars nicht ausreichen.

Einige Benutzereingaben enthalten Sonderzeichen, die von den obigen Funktionen nicht entfernt werden. In diesen Fällen muss ich Folgendes tun:

preg_replace('/[\x00-\x1f]/','',htmlspecialchars($string))

Dadurch werden auch bestimmte xml-unsafe Steuerzeichen wie Null character oder EOT entfernt. Mit dieser table können Sie bestimmen, welche Zeichen Sie weglassen möchten.

4
Reuben L.

Ich bevorzuge die Art und Weise, wie Golang für XML Escapeing verwendet (und ein paar Extras wie Newline-Escape und andere Zeichen), also habe ich seine XML-Escape-Funktion nach PHP portiert

function isInCharacterRange(int $r): bool {
    return $r == 0x09 ||
            $r == 0x0A ||
            $r == 0x0D ||
            $r >= 0x20 && $r <= 0xDF77 ||
            $r >= 0xE000 && $r <= 0xFFFD ||
            $r >= 0x10000 && $r <= 0x10FFFF;
}

function xml(string $s, bool $escapeNewline = true): string {
    $w = '';

    $Last = 0;
    $l = strlen($s);
    $i = 0;

    while ($i < $l) {
        $r = mb_substr(substr($s, $i), 0, 1);
        $Width = strlen($r);
        $i += $Width;
        switch ($r) {
            case '"':
                $esc = '&#34;';
                break;
            case "'":
                $esc = '&#39;';
                break;
            case '&':
                $esc = '&amp;';
                break;
            case '<':
                $esc = '&lt;';
                break;
            case '>':
                $esc = '&gt;';
                break;
            case "\t":
                $esc = '&#x9;';
                break;
            case "\n":
                if (!$escapeNewline) {
                    continue 2;
                }
                $esc = '&#xA;';
                break;
            case "\r":
                $esc = '&#xD;';
                break;
            default:
                if (!isInCharacterRange(mb_ord($r)) || (mb_ord($r) === 0xFFFD && $Width === 1)) {
                    $esc = "\u{FFFD}";
                    break;
                }

                continue 2;
        }
        $w .= substr($s, $Last, $i - $Last - $Width) . $esc;
        $Last = $i;
    }
    $w .= substr($s, $Last);
    return $w;
}

Beachten Sie, dass Sie mindestens PHP7.2 benötigen, da mb_ord verwendet wird, oder Sie müssen es gegen eine andere Polyfill austauschen. Diese Funktionen funktionieren jedoch hervorragend für uns!

Für Neugierige ist hier die relevante Go-Quelle https://golang.org/src/encoding/xml/xml.go?s=44219:44263#L1887

0
Brian Leishman