41 Stimmen

Escape-Zeichenfolgen zur Verwendung in XML

Ich verwende Pythons xml.dom.minidom um ein XML-Dokument zu erstellen. (Logische Struktur -> XML-String, nicht umgekehrt.)

Wie kann ich dafür sorgen, dass die von mir bereitgestellten Zeichenfolgen entkommen, damit sie das XML nicht durcheinanderbringen können?

86voto

mbarkhau Punkte 7822

So etwas wie das hier?

>>> from xml.sax.saxutils import escape
>>> escape("< & >")   
'&lt; &amp; &gt;'

23voto

MichaelMoser Punkte 2876

Xml.sax.saxutils vermeidet keine Anführungszeichen (")

Hier ist also eine weitere:

def escape( str ):
    str = str.replace("&", "&amp;")
    str = str.replace("<", "&lt;")
    str = str.replace(">", "&gt;")
    str = str.replace("\"", "&quot;")
    return str

Wenn Sie nachschauen, dann ersetzt xml.sax.saxutils nur Strings

19voto

K L Punkte 256

xml.sax.saxutils.escape entweicht nur & , < et > standardmäßig, aber es bietet eine entities Parameter, um zusätzlich andere Zeichenketten zu entschlüsseln:

from xml.sax.saxutils import escape

def xmlescape(data):
    return escape(data, entities={
        "'": "&apos;",
        "\"": "&quot;"
    })

xml.sax.saxutils.escape verwendet str.replace() intern, Sie können also auch den Import überspringen und Ihre eigene Funktion schreiben, wie in der Antwort von MichealMoser gezeigt.

15voto

Andrey Vlasovskikh Punkte 15947

Sie meinen, Sie machen so etwas:

from xml.dom.minidom import Text, Element

t = Text()
e = Element('p')

t.data = '<bar><a/><baz spam="eggs"> & blabla &entity;</>'
e.appendChild(t)

Dann erhalten Sie einen schön escapeten XML-String:

>>> e.toxml()
'<p>&lt;bar&gt;&lt;a/&gt;&lt;baz spam=&quot;eggs&quot;&gt; &amp; blabla &amp;entity;&lt;/&gt;</p>'

11voto

user590028 Punkte 10717

Die akzeptierte Antwort von Andrey Vlasovskikh ist die vollständigste Antwort auf das OP. Aber dieses Thema taucht bei den häufigsten Suchen nach python escape xml und ich wollte einen Zeitvergleich der drei diskutierten Lösungen anbieten Ich wollte einen Zeitvergleich der drei in diesem Artikel besprochenen Lösungen anbieten und außerdem eine vierte Option vorstellen, die wir aufgrund ihrer verbesserten Leistung gewählt haben.

Alle vier basieren entweder auf der nativen Python-Datenverarbeitung oder der Python-Standardbibliothek. Die Lösungen werden in der Reihenfolge von der langsamsten zur schnellsten Leistung angeboten.

Option 1 - regex

Diese Lösung verwendet die Python-Regex-Bibliothek. Sie liefert die langsamste Leistung:

import re
table = {
    "<": "&lt;",
    ">": "&gt;",
    "&": "&amp;",
    "'": "&apos;",
    '"': "&quot;",
}
pat = re.compile("({})".format("|".join(table)))

def xmlesc(txt):
    return pat.sub(lambda match: table[match.group(0)], txt)

>>> %timeit xmlesc('<&>"\'')
1.48 µs ± 1.73 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Zu Ihrer Information: µs ist das Symbol für Mikrosekunden, was 1 Millionstel Sekunde entspricht. Die Fertigstellungszeiten der anderen Implementierungen werden in Nanosekunden (ns) gemessen, was dem Milliardstel einer Sekunde entspricht.

Möglichkeit 2: xml.sax.saxutils

Diese Lösung verwendet python xml.sax.saxutils Bibliothek.

from xml.sax.saxutils import escape
def xmlesc(txt):
    return escape(txt, entities={"'": "&apos;", '"': "&quot;"})

>>> %timeit xmlesc('<&>"\'')
832 ns ± 4.3 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Option 3 - str.replace

Diese Lösung verwendet die Zeichenfolge replace() Methode. Unter der Haube implementiert sie eine ähnliche Logik wie Pythons xml.sax.saxutils . Der saxutils-Code hat eine for-Schleife, die etwas Leistung kostet, was diese Version etwas schneller macht.

def xmlesc(txt):
    txt = txt.replace("&", "&amp;")
    txt = txt.replace("<", "&lt;")
    txt = txt.replace(">", "&gt;")
    txt = txt.replace('"', "&quot;")
    txt = txt.replace("'", "&apos;")
    return txt

>>> %timeit xmlesc('<&>"\'')
503 ns ± 0.725 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Option 4 - str.translate

Dies ist die schnellste Implementierung. Sie verwendet die Zeichenkette translate() método.

table = str.maketrans({
    "<": "&lt;",
    ">": "&gt;",
    "&": "&amp;",
    "'": "&apos;",
    '"': "&quot;",
})
def xmlesc(txt):
    return txt.translate(table)

>>> %timeit xmlesc('<&>"\'')
352 ns ± 0.177 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

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