Seite 1 von 1

minidom, encoding und encoder [erledigt]

Verfasst: Donnerstag 26. Juni 2008, 15:21
von ChrisGTJ
Hallo,

ich versuche mit minidom einen xml-String zu parsen. Wenn ich den String einfach mal mit print 'rausschreibe, sieht er ganz normal aus (ist auch klar, weil er in cp1252 kodiert ist). Ein Teil des Strings könnte so aussehen:

Code: Alles auswählen

<Name>Gerät 1</Name>
So weit, so schön. Wenn ich nun aber den Parser drauf loslasse, bekomme ich einen Fehler:

Code: Alles auswählen

xml.parsers.expat.ExpatError: not well-formed (invalid token): line 1, column 9
Es sieht so aus, als käme der Parser mit dem 'ä' nicht klar, denn wenn ich es austausche, klappt es.

Frage 1:
Kann ich dem Parser mitteilen, was für ein encoding der String hat?

Frage 2:
Ich könnte den String umkodieren:

Code: Alles auswählen

import codecs
from xml.dom.minidom import parseString
boxXml = "<Name>Gerät 1</Name>".encode( "cp1252")
utf8Encoder = codecs.getencoder( "utf_8")
newXml = utf8Encoder( boxXml)[0]
dom1 = parseString( newXml)  # klappt
dom2 = parseString( boxXml)  # produziert obigen Fehler
Aber:
Woher weiß der encoder, wovon er ausgehen muß? Soll heißen:

Woher weiß der utf_8-encoder, daß er mein 'ä' bitteschön als utf_8-'ä' zu interpretieren hat? Es kann doch sein, daß die Zahl 'ä' (ein Wert zwischen 0 und 255, in c-Notation sozusagen) in einem anderen Zeichensatz als cp1252 vielleicht ein 'Z' repräsentiert.

Wenn der encoder also umcodiert, von einer Darstellung in eine andere, woher kennt er die Zuordnungen?

Vielleicht bin ich auf dem Holzweg und sehe den Baum im Wald nicht. Kann jemand von Euch Licht ins Dunkel bringen?

Gruß und Danke,

Christoph

Verfasst: Donnerstag 26. Juni 2008, 17:02
von cofi
Ich denke du solltest - sofern das geht - einfach die XML-Standartkodierung UTF-8 verwenden.
Bei mir klappt das problemlos.

Ich denke daran liegt auch dein Problem, dass du im Code beschreibst: Du lässt den Parser auch nen cp1252-kodiertes Stückchen los ;)

Verfasst: Donnerstag 26. Juni 2008, 20:26
von Hyperion
Eben! Wenn Du weißt, dass Du eine cp-1251 codierte Datei einliest (die ja dann übrigens per definitionem nicht XML ist ;-) ), dann decodiere sie doch vor dem Parsen in Unicode. Das sollte Dein Problem lösen.

Verfasst: Donnerstag 26. Juni 2008, 20:48
von BlackJack
XML-Parser wollen Bytes und kein Unicode.

Verfasst: Donnerstag 26. Juni 2008, 21:30
von lunar
BlackJack hat geschrieben:XML-Parser wollen Bytes und kein Unicode.
Weil XML nämlich die Angabe des Encoding in der XML-Deklaration ermöglicht, so dass der Parser die Dekodierung automatisch vornehmen kann.

Verfasst: Donnerstag 26. Juni 2008, 21:41
von Hyperion
Ok, dann wird der Fehler also produziert, weil Das Encoding cp-1251 dem Parser nicht bekannt ist oder weil die Angabe in der Datei nicht simmt, richtig?

Verfasst: Freitag 27. Juni 2008, 10:44
von ChrisGTJ
Hallo,

danke für die Antworten.

Die Kodierung ist genau das Problem, wie mein Beispiel zeigt. Da der originale xml-String aus einem COM/DCOM-Objekt kommt, nehme ich mal cp1252 als Kodierung an. Jetzt noch mal die Kernfrage:

Woher weiß encode(), daß der String, von dem es ausgeht, in cp1252 kodiert ist?

Gruß,

Christoph

PS: Das Beispiel geht auch einfacher:

Code: Alles auswählen

from xml.dom.minidom import parseString
boxXml = "<Name>Gerät 1</Name>".encode( "cp1252")
utfXml = boxXml.encode( "utf_8")
dom1 = parseString( utfXml)  # klappt
dom2 = parseString( boxXml)  # produziert obigen Fehler

Verfasst: Freitag 27. Juni 2008, 11:09
von Leonidas
ChrisGTJ hat geschrieben:Woher weiß encode(), daß der String, von dem es ausgeht, in cp1252 kodiert ist?
Weiß es nicht. Das ist ja eben der Punkt, warum man Encodings angeben muss.

Verfasst: Freitag 27. Juni 2008, 12:33
von ChrisGTJ
Leonidas hat geschrieben:
ChrisGTJ hat geschrieben:Woher weiß encode(), daß der String, von dem es ausgeht, in cp1252 kodiert ist?
Weiß es nicht. Das ist ja eben der Punkt, warum man Encodings angeben muss.
Ja eben.

Vielleicht ist mein Problem ein Denkfehler:

Ich denke, daß die Methode encode() eine Übersetzung macht. Soll heißen, es nimmt einen Sack voller Bytes und baut ihn um, von encoding Typ A nach Typ B, indem alle Sachen aus A, die B nicht kennt, so dargestellt werden, daß B sie wieder kennt (alles klar? ;)). Aber: Stimmt diese Annahme überhaupt?

Gruß,

Christoph

Verfasst: Freitag 27. Juni 2008, 15:01
von BlackJack
Nein, die Annahme stimmt nicht. `encode()` wandelt *Unicode* in einen Sack voll Bytes um. Wenn Du einen Sack voll Bytes von einer Kodierung in die andere befördern willst, musst Du `decode()` und `encode()` nacheinander verwenden und beide Kodierungen explizit angeben.

Verfasst: Freitag 27. Juni 2008, 15:47
von ChrisGTJ
BlackJack hat geschrieben:Nein, die Annahme stimmt nicht. `encode()` wandelt *Unicode* in einen Sack voll Bytes um. Wenn Du einen Sack voll Bytes von einer Kodierung in die andere befördern willst, musst Du `decode()` und `encode()` nacheinander verwenden und beide Kodierungen explizit angeben.
Nachdem es uns nun wie Schuppen aus den Haaren fällt, können wir nach Hause gehen. :)

Danke für die Info!

Christoph