Entities in der Ausgabe durch Umlaute ersetzen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
christine
User
Beiträge: 31
Registriert: Dienstag 24. Februar 2009, 10:03

Hallo,

ich habs wieder mal etwas Umständlich...

Ich habe eine dynamisch generierte Liste. Wenn in dieser Liste Wörter sind in denen Entities der Form ä ü ö [auch Großschreibung] vorkommen, möchte ich den String ändern(bzw. ersetzen), so das die Entities ersetzt werden.

Mein Stand momentan:
Ich zerteile den String und setze ihn neu zusammen.
Das geht so aber nur wenn das Wort nur einen Umlaut enthält.
Und momentan nur mit ä

Code: Alles auswählen

# alle wörter aus der Liste gewerberaum die ä enthalten, werden stattdessen mit ä ausgegeben

        for wort in gewerberaum:
            wort = wort.split('ä')
            if len(wort)>=2: 
                neuesWort = wort[0]+ "ä" + wort[1]
                print neuesWort
            elif len(wort)<=1:
                neuesWort = wort[0]
                print neuesWort
        print '\n'
meine Idee war eine geordnetet Liste zu erstellen:

Code: Alles auswählen

umlaut = {0:'ä', 1:'ö', 2:'ü', 3:'Ä', 4:'Ö', 5:'Ü' }
und dann :

Code: Alles auswählen

for wort in gewerberaum:
            wort = wort.split(umlaut)
aber das Funktioniert nicht. Python erwartet ein "character buffer object"

Ich bin mir gerade auch nicht sicher ob ich völlig in die falsche Richtung abziele.
Vieleicht gibt es ja ein Modul o.ä. das ich einsetzen kann?

Danke, Grüße,
Christine
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Suchst du eventuell sowas? Zumindest das definieren der Entities ist unnötig, schließlich hat Python die in der Stdlib (und dir fehlt ``&szlig;``).
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
christine
User
Beiträge: 31
Registriert: Dienstag 24. Februar 2009, 10:03

Hi Leonidas,

htmlentitydefs ist ja interessant.
So ganz kapiere ich die Methode noch nicht. Aber ich arbeite daran :)

Danke, Grüße,
Christine
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Ich würde sagen, dass HTML-Entities ein Anachronismus sind. Browser und Webserver sollten ja wohl schon seit Äonen 8-bit-sicher sein und unterstützen alle seit Jahren UTF-8, was einem den gesamten Unicode-Zeichenvorrat zu benutzen erlaubt. Wozu die Zeichen also noch Mal in HTML kodieren?

Stefan
christine
User
Beiträge: 31
Registriert: Dienstag 24. Februar 2009, 10:03

hi sma,

ich bekomme als Augabe Wörter mit entities aber ich möchte
die entities als Umlaute ausgeben. Damit die Lesbarkeit verbessert wird.
Es geht um Auswertung von sgml Dateien.

Den Hinweis auf htmlentitydefs fand ich interessant. Wenn man nicht weiss was es alles gibt, kann man schlechter Probleme lösen.
leider hab ich die vorgestellte Methode nicht kapiert, dafür muss ich noch mehr in die Stringoperationen einsteigen.

ich habe es jetzt so realisiert:
methode:

Code: Alles auswählen

....
text = text.replace('ü', 'ü')
....
Grüße,
Christine
Benutzeravatar
helduel
User
Beiträge: 300
Registriert: Montag 23. Juli 2007, 14:05
Wohnort: Laupheim

Moin,

dann mal Zeile für Zeile:

Code: Alles auswählen

def unescape(text):
    # Eine innere funktion wird definiert; diese könnte natürlich auch
    # außerhalb definiert werden. fixup gibt für das jeweilige Entity
    # das entsprechende Zeichen zurück (ä für ä, etc.).
    def fixup(m):
        # der fixup-Funktion wird ein match-Objekt einer Regular Expression
        # übergeben. Die folgende Zeile holt den gematchten String. In
        # diesem Fall wird das immer ein Entity sein.
        text = m.group(0)
        # Wenn das Entity mit &# anfängt, dann handelt es sich um eine
        # dezimale Angabe des Zeichens in Unicode.
        if text[:2] == "&#":
            try:
                # mit einem x hinten dran ist die angabe hexadezimal
                if text[:3] == "&#x":
                    # Das entsprechende Unicode-Zeichen wird zurückgegeben.
                    # Der Hex-Wert wird hierzu zu einem dezimalen Wert 
                    # umgewandelt.
                    return unichr(int(text[3:-1], 16))
                else:
                    # Das dem dezimalen Wert entsprechende Unicode-Zeichen
                    # wird zurückgegeben.
                    return unichr(int(text[2:-1]))
            except ValueError:
                pass
        else:
            # named entity
            try:
                # name2codepoint ist ein Mapping von der Entity zu dem 
                # jeweiligen dezimalen Unicode-Wert. Das entsprechende 
                # Zeichen wird zurückgegeben. text[1:-1] schneidet das "&"
                # und das ";" ab, um nur den Entity-Namen zu suchen.
                text = unichr(htmlentitydefs.name2codepoint[text[1:-1]])
            except KeyError:
                pass
        # wenn alles fehlschlgt, wird nichts umgewandelt.
        return text # leave as is
    # Hier wird die substitute-Funktion der Regular Expressions aufgerufen.
    # Der Filter "&#?\w+;" Findet alle Entities in der Form von "{",
    # "&#xC3" oder "ä". Der gefundene Entity-String wird in einem
    # Match-Object gekapselt und der fixup-Funktion übergeben. Die 
    # gefundene Entity wird durch den String, den fixup liefert, ersetzt.
    return re.sub("&#?\w+;", fixup, text)
Ich würde allerdings die Regex zu "&#?\w+?;" ändern, damit sie nicht greedy ist und lauter Müll matcht, bis mal ein richtiges Entity vorbeischneit.

Gruß,
Manuel
BlackJack

@sma: Reine ASCII-Ausgabe kann zur Fehlersuche nützlich sein, genauso wie `repr()` bzw. `ascii()` sich auf ASCII beschränken. Man kann sich das halt irgendwo hin "dumpen" und sich sicher sein, was man da hat, egal wie die Kodierung des Terminals oder des Texteditors eingestellt ist, mit dem man sich die "Rohdaten" anschaut.

Auch bei der Eingabe ist es nützlich, wenn man nicht weiss wie man Sonderzeichen auf der Tastatur erzeugen kann.

@christine: Wenn Du wirklich mit Zeichen arbeiten willst, solltest Du auf Unicode setzen.
christine
User
Beiträge: 31
Registriert: Dienstag 24. Februar 2009, 10:03

Wow, Danke Manuel 8)

@BlackJack: wie meinst du das, ich soll auf Unicode gehen?
ich bekomme die Daten ja aus einer sgml Datei und möchte sie "leserlich"
ausgeben...versteh ich jetzt nicht ganz.

wenn ich das coding in meiner .py Datei als Unicode angebe, besagt das doch nur, daß die Datei Unicode codiert ist?! Aber hat das dann eine Auswirkung auf die Daten die ich in die Datei einlese?
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

*seufz* ... mit solchen Fragen bin ich hier auch seinerzeit verzweifelt eingestiegen ;-) Kann Deine Verwirrung als bestens verstehen!

Anbei mal ein paar informative Links:
[wiki]Unicode[/wiki]
[wiki]Von Umlauten, Unicode und Encodings[/wiki]

Generell eine Aussage, die man einfach akzeptieren muss:
Unicode ist nichts "greifbares", sondern ein Konzept!

Alles was im Quellcode steht, oder auf der Konsole oder in eine Datei geschrieben wird ist kein Unicode! utf-8 usw. ist nur eine bestimmte Kodierung von Zeichen.

Von außen bekommst Du in Dein Pythonprogramm also immer Zeichen in einer bestimmten Kodierung, etwa iso-8859-1 oder utf-8 oder eben das unsägliche ASCII ;-)

Diese solltest Du dann möglichst schnell (also an der Stelle, wo Du die Daten erhältst) in Unicode wandeln. Das geht per

Code: Alles auswählen

data.decode("codierung")
Intern arbeitest Du dann mit Unicode-Strings. Willst Du direkt in Deinem Script Unicode-Strings anlegen schreibst Du ein kleines "u" vor die Zeichenkette:

Code: Alles auswählen

test = u"Unicode-String"
Was da steht ist natürlich auch in einer bestimmten Kodierung gespeichert, nämlich in der, mit der Du deine Scriptdatei speicherst! Das gibt man ja oben in einer Datei per -*- coding: ... -*- an - wobei das mit der tatsächlichen Kodierung übereinstimmen sollte, mit der man die Datei speichert.

Nun kann Python die Zeichenketten, die im Script stehen, automatisch in Unicode decodieren!

Wenn man zu einem Zeitpunkt wieder etwas speichern oder ausgeben will, so muss man die Unicode-Strings encodieren, also wieder in ein Encoding bringen, dass für das Ausgabemedium oder die Weiterverarbeitung geeignet ist.

Das geht per

Code: Alles auswählen

test.encode("codierung")
Es gibt da einige Helferlein, die das Default-Encoding des OS bestimmen oder das von stdout.

Sehr hilfreich war für mich der Vortrag von Leonidas:
[wiki]User Group München[/wiki]?action=AttachFile&do=get&target=unicode-folien.pdf

So, ich habe mir immer vorgenommen nichts mehr zur Thematik zu posten, weil auch ich da noch nicht alles zu 100% durchblickt habe ... hoffe mal, dass keine groben fehler drin stehen :-D
BlackJack

@christine: Wenn Du ``text = text.replace('&uuml;', 'ü')`` verwendest, dann steht in `text` am Ende ein oder mehrere Bytes anstelle des '&uuml;', die in der Kodierung Deines Quelltextes ein 'ü' darstellen. Wenn Du das "leserlich" ausgeben kannst, dann scheint das Programm, was letztendlich für die Ausgabe zuständig ist, die gleiche Kodierung zu erwarten, die Du im Quelltext verwendest.

Ob das reicht, hängt vom Anwendungszweck ab.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

BlackJack hat geschrieben:@sma: Reine ASCII-Ausgabe kann zur Fehlersuche nützlich sein, genauso wie `repr()` bzw. `ascii()` sich auf ASCII beschränken.
Auch legacy. Mein Terminal kann UTF-8 und wenn ich ein Zeichen nicht erkennen kann, dann kann dieses bitte einen Tooltip oder ähnliches bieten. In der Regel will ich ja schauen, was in einem String steht und nicht, wie das System ihn wohl kodieren würde. Letzteres ist IMHO ein spezialfall, für den man gerne eine Methode "".hexdump() oder ähnliches haben könnte. Python 3 macht es dann auch richtig.

Da es aber offenbar um SGML-Dateien mit Entities geht, die gerade entfernt werden sollen, ist meine Bemerkung eh nicht zielführend gewesen.

Was ich noch zu Python < 3.0 anmerken würde: Nie einfache Byte-Strings benutzen, sondern immer Unicode-Strings. Sonst erlebt man komische Überraschungen, was die Umlaute angeht. Schrieb Hyperion schon...

Stefan
BlackJack

Den Einwand verstehe ich nicht. Wenn ich debugge, will ich wissen was genau da steht, nicht was die UTF-8 Dekodierung des Terminals daraus macht. Vor allem dann, wenn die Ausgabe gar nicht UTF-8 ist, und ich so gar nicht mehr erkennen kann, was eigentlich ausgegeben werden sollte, weil einiges zu Kästchen bzw. Fragezeichen wird, und andere Bytes vielleicht sogar komplett verschluckt werden.

Und wenn man dann so eine Ausgabe in ein Forum oder an eine Mailingliste schickt, muss man auch wieder mit angeben welche Kodierung das Terminal hatte (wenn man das denn überhaupt weiss) und hoffen, dass die Sonderzeichen den Transport zu den potentiellen Helfern überleben. Also zur Fehlersuche finde ich eine robuste, eindeutige Darstellung, die sich auf ASCII beschränkt, sehr nützlich.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

BlackJack hat geschrieben:Den Einwand verstehe ich nicht. Wenn ich debugge, will ich wissen was genau da steht, nicht was die UTF-8 Dekodierung des Terminals daraus macht.
Eine Frage der Sichtweise. Was du UTF-8-Dekodierung nennst, nenne ich das Original, nämlich die Unicode-Zeichen. Die will ich im Original sehen und nicht eine Umschreibung in Form von UTF-8 und das auch noch als \x-Hexzahlen. Ich will nicht wissen müssen, dass das Euro-Zeichen auf 0x20ac liegt (dessen UTF-8 Umschreibung weiß ich nicht auswendig), sondern es einfach sehen.

Stefan
BlackJack

Aber das Problem beim Debuggen ist doch, dass Du dem was Du siehst eventuell nicht trauen kannst. Die Probleme tauchen typischerweise ja auf, wenn auf dem Weg von einem Ende des Datenwegs durch das Programm zum anderen Ende irgendwo beim hin- und herkodieren etwas schief läuft. Also zum Beispiel Datenbank an einem Ende, Webanwendung die eine Mail verschickt am anderen Ende. Wenn da Murks rauskommt, dann möchte ich bei der Fehlersuche gerne die Rohdaten an den verschiedenen Stationen im Programm in einer eindeutigen Form sehen, und nicht raten müssen, ob Kodierung der Daten und des Anzeigemediums nun zufällig (nicht) zusammenpassen und welche das überhaupt ist.
christine
User
Beiträge: 31
Registriert: Dienstag 24. Februar 2009, 10:03

Hallo @ all!

Vielen Dank für eure Hilfe und Antworten.
Werde mich dann mal über Unicode und Codings schlauer machen
-> Danke für die Links
:)

Grüße,
Christine
Antworten