Seite 1 von 2
Lesen und Schreiben von kvtml Vokabeldateien
Verfasst: Dienstag 11. Mai 2010, 14:00
von Ubuntuxer
Ich versuche eine kleine Bibliothek zu erstellen, die das Lesen und Schreiben von kvtml Vokabeldateien ermöglicht.
Das kvtml Format ist ein Dateiformat, welches große Ähnlichkeiten mit XML Dateien hat. Das Auslesen und Schreiben sollte deshalb eigentlich problemlos mit der Standartbibliothek xml.etree.ElementTree möglich sein.
Ich bin allerdings auf zwei Probleme gestoßen, die ich trotz durcharbeiten der Referenz zu xml.etree.ElementTree nicht lösen konnte.
1) Strings mit Umlauten werden beim Auslesen automatisch in Unicodes umgewandelt; Wie kann ich die wieder in Utf-8 Strings umwandeln?
2) Wie kann ich die ersten beiden Zeilen der kvtml erstellen, also die Angaben über die xml version und encoding sowie den Doctype.
Ich bin mir mittlerweile ziemlich sicher das es nicht mit der Bibliothek xml.etree.ElementTree geht, aber selbst bei lxml habe ich nichts gefunden.
Mein bisheriger Code sieht so aus:
http://www.python-forum.de/pastebin.php?mode=view&s=4
Eine kvtml Vokabeldatei hat das folgende Format:
http://www.python-forum.de/pastebin.php?mode=view&s=5
PS: Die beiden Dateien die ich hochgeladen habe stehen unter der GPL.
Re: Lesen und Schreiben von kvtml Vokabeldateien
Verfasst: Dienstag 11. Mai 2010, 15:06
von Dauerbaustelle
Ubuntuxer hat geschrieben:Wie kann ich die wieder in Utf-8 Strings umwandeln?
xml version und encoding sowie den Doctype.
Das Erstere sollte eigentlich automatisch dazukommen. Zweiteres musst du wohl von Hand hinzufügen.
Ich empfehle dir auf jeden Fall lxml, weil das Hunderte Male schneller und schlanker ist.
Re: Lesen und Schreiben von kvtml Vokabeldateien
Verfasst: Dienstag 11. Mai 2010, 15:13
von BlackJack
@Ubuntuxer: Warum willst Du die Unicode-Objekte überhaupt als `str` haben? Wenn man mit Zeichen arbeiten will, ist `unicode` doch eigentlich genau das, was man eigentlich möchte!?
Re: Lesen und Schreiben von kvtml Vokabeldateien
Verfasst: Dienstag 11. Mai 2010, 15:15
von Hyperion
Ubuntuxer hat geschrieben:
Das kvtml Format ist ein Dateiformat, welches große Ähnlichkeiten mit XML Dateien hat.
Das
ist xml

Re: Lesen und Schreiben von kvtml Vokabeldateien
Verfasst: Dienstag 11. Mai 2010, 19:06
von Ubuntuxer
Dauerbaustelle hat geschrieben:
Das Problem ist, dass die HTML Ersatzzeichen für die Umlaute nicht wieder in Umlaute umgewandelt werden.
u'T\xfcr'.encode('utf-8')
'T\xc3\xbcr'
Der KDE Vokabeltrainer Parley kann mit diesen Zeichen nicht umgehen, sodass nur die Sprache ohne Umlaute korrekt aus meiner erzeugten Datei eingelesen wird.

@Blackjack: Parley kann auch mit Unicodes nicht umgehen.
xml version und encoding sowie den Doctype.
Das Erstere sollte eigentlich automatisch dazukommen. Zweiteres musst du wohl von Hand hinzufügen.
Und wie füge ich den Doctype per Hand hinzu???
Wenn ich eine Datei einlese und danach neu schreibe sieht sie wie folgt aus:
http://www.python-forum.de/pastebin.php ... &mode=view
Ich empfehle dir auf jeden Fall lxml, weil das Hunderte Male schneller und schlanker ist.[/quote]
Ich meine xml.etree.cElementTree sei noch schneller als lxml, aber das ist mir eigentlich total egal. Hauptsache es funktioniert überhaupt!
Re: Lesen und Schreiben von kvtml Vokabeldateien
Verfasst: Dienstag 11. Mai 2010, 19:27
von BlackJack
@Ubuntuxer: Dann kann Parley nicht mit XML umgehen, was ich jetzt nicht so recht glauben mag, denn dann wäre das Programm für die Tonne.
Re: Lesen und Schreiben von kvtml Vokabeldateien
Verfasst: Dienstag 11. Mai 2010, 19:34
von BlackJack
@Ubuntuxer: Das würde insbesondere auch bedeuten das Parley nicht mit der Datei klarkommt, die Du da gezeigt hast, denn da sehe ich in Zeile 14 bei "Niederländisch" ziemlich deutlich ein 'ä'.
Ich habe da eher den Verdacht das Du etwas falsch machst. XML (das DOM) ist mit Unicode definiert, das kennt kein UTF-8. Die Zeichenketten mit Umlauten, welche Du als `unicode` bekommst, musst Du auch wieder als `unicode` in XML-Element-Objekte reinstecken! *Nicht* als UTF-8 kodierte `str`-Objekte -- da kommt Murks bei raus. Das ist einer der Gründe warum ich gefragt habe, warum Du die überhaupt kodieren willst.
Re: Lesen und Schreiben von kvtml Vokabeldateien
Verfasst: Dienstag 11. Mai 2010, 19:47
von Dauerbaustelle
Ubuntuxer, siehe folgende Grafiken (weniger ist schneller ist besser):
Parsing
Serialization
(
Quelle)
Re: Lesen und Schreiben von kvtml Vokabeldateien
Verfasst: Dienstag 11. Mai 2010, 19:55
von BlackJack
@Dauerbaustelle: Ich zweifle mal die Relevanz an, weil es da ja wohl um potentiell kaputtes HTML geht und mir zumindest jetzt nicht klar ist, wieviel zusätzlichen Aufwand das jeweils macht das vorzuverarbeiten oder irgendwie anders beim Parsen zu berücksichtigen.
Kann ja zum Beispiel sein dass die beim reinen Parsen vom XML alle gleich schnell sind, sich aber in der "Korrekturphase" vorher unterschiedlich lange aufhalten.
Re: Lesen und Schreiben von kvtml Vokabeldateien
Verfasst: Dienstag 11. Mai 2010, 20:12
von Dauerbaustelle
lxml hat ein eingebautes html-Modul, das das Parsen von kaputten HTML ziemlich effizient managed.
Re: Lesen und Schreiben von kvtml Vokabeldateien
Verfasst: Dienstag 11. Mai 2010, 20:36
von BlackJack
@Dauerbaustelle: Das untermauert, dass die Zahlen hier wertlos sind, weil der Unterschied zu einem relevanten Anteil im HTML-Teil liegen könnte. Um HTML geht es hier aber gar nicht.
Re: Lesen und Schreiben von kvtml Vokabeldateien
Verfasst: Dienstag 11. Mai 2010, 21:51
von Ubuntuxer
BlackJack hat geschrieben:@Ubuntuxer: Das würde insbesondere auch bedeuten das Parley nicht mit der Datei klarkommt, die Du da gezeigt hast, denn da sehe ich in Zeile 14 bei "Niederländisch" ziemlich deutlich ein 'ä'.
Ich habe da eher den Verdacht das Du etwas falsch machst. XML (das DOM) ist mit Unicode definiert, das kennt kein UTF-8. Die Zeichenketten mit Umlauten, welche Du als `unicode` bekommst, musst Du auch wieder als `unicode` in XML-Element-Objekte reinstecken! *Nicht* als UTF-8 kodierte `str`-Objekte -- da kommt Murks bei raus. Das ist einer der Gründe warum ich gefragt habe, warum Du die überhaupt kodieren willst.
Ich versuche einfach mal noch genauer zu beschreiben wo mein Problem liegt:
Ich parse zunächst die Orginal kvtml Datei von Parley und dabei z.B. das Wort "Niederländisch"
Die Bibliothek xml.etree.cElementTree wandelt seltsamerweise Wörter mit Umlauten in einen Unicode um, während Wörter ohne Umlaut normale Strings bleiben.
Dies bedeutet das Wort Niederländisch wird zu u'Niederl\xe4ndisch'.
Ich könnte das eingelesene Wort direkt in einen String umwandeln.
u'Niederl\xe4ndisch'.encode('utf-8') => 'Niederl\xc3\xa4ndisch'
Nun möchte ich die eingelesen Informationen wieder in eine neue kvtml Datei schreiben.
Code: Alles auswählen
text = ETree.SubElement(entry, "text")
text.text = u'Niederl\xe4ndisch'
Dann steht in meiner neuen kvtml Datei <text>u'Niederl\xe4ndisch'</text>.
Code: Alles auswählen
text = ETree.SubElement(entry, "text")
text.text = u'Niederl\xe4ndisch'.encode('utf-8')
Dann steht in meiner neuen kvtml Datei <text>'Niederl\xc3\xa4ndisch'</text>
Beides kann Parley nicht lesen.
Ich vermute einfach mal, dass xml.etree.cElementTree die Information braucht, wie es die zugewiesen Unicodes encoden soll. In der Orginaldatei steht ja auch: <?xml version="1.0" encoding="UTF-8"?>
Ohne die beiden Zeilen ersten Zeilen der Orginaldatei kann Parley meine erstellte Datei überhaupt nicht lesen.
Code: Alles auswählen
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE kvtml PUBLIC "kvtml2.dtd" "http://edu.kde.org/kvtml/kvtml2.dtd">
Re: Lesen und Schreiben von kvtml Vokabeldateien
Verfasst: Dienstag 11. Mai 2010, 22:11
von Dauerbaustelle
BlackJack hat geschrieben:Um HTML geht es hier aber gar nicht.
Du hast aber was davon erzählt o_O
Re: Lesen und Schreiben von kvtml Vokabeldateien
Verfasst: Dienstag 11. Mai 2010, 22:15
von Hyperion
Also mit lxml kein Problem:
Code: Alles auswählen
In [17]: from lxml import etree
In [18]: with open("kvtml.xml", "r") as infile:
tree = etree.parse(infile)
....:
....:
In [20]: tree
Out[20]: <lxml.etree._ElementTree object at 0xb75adecc>
In [21]: tree.docinfo
Out[21]: <lxml.etree.DocInfo object at 0xb72eea34>
In [22]: tree.docinfo.doctype
Out[22]: u'<!DOCTYPE kvtml PUBLIC "kvtml2.dtd" "http://edu.kde.org/kvtml/kvtml2.dtd">'
In [23]: tree.docinfo
tree.docinfo
In [23]: tree.docinfo.
tree.docinfo.URL tree.docinfo.__reduce__ tree.docinfo.externalDTD
tree.docinfo.__class__ tree.docinfo.__reduce_ex__ tree.docinfo.internalDTD
tree.docinfo.__delattr__ tree.docinfo.__repr__ tree.docinfo.public_id
tree.docinfo.__doc__ tree.docinfo.__setattr__ tree.docinfo.root_name
tree.docinfo.__format__ tree.docinfo.__sizeof__ tree.docinfo.standalone
tree.docinfo.__getattribute__ tree.docinfo.__str__ tree.docinfo.system_url
tree.docinfo.__hash__ tree.docinfo.__subclasshook__ tree.docinfo.xml_version
tree.docinfo.__init__ tree.docinfo.doctype
tree.docinfo.__new__ tree.docinfo.encoding
In [23]: text = etree.Element("text")
In [24]: text.text = u"Niederländisch"
In [25]: text.text
Out[25]: u'Niederl\xc3\xa4ndisch'
In [26]: print text.text.encode("latin-1")
-------> print(text.text.encode("latin-1"))
Niederländisch
(Bei mir ist in der Shell wohl latin-1 als default encoding eingestellt. Muss ich mal nachprüfen... ist ja vollkommen ätzend!)
Aber wie Du siehst kümmert sich lxml auch um Header-Infos. Kann mir aber nicht vorstellen, dass die ElementTree-API aus der Standard-Lib das nicht tut.
Re: Lesen und Schreiben von kvtml Vokabeldateien
Verfasst: Dienstag 11. Mai 2010, 22:33
von BlackJack
@Ubuntuxer: Das Zeichenketten mit Umlauten als `unicode`-Objekte von den diversen XML-Bibliotheken geliefert werden ist nicht seltsam sondern das normale Verhalten. Seltsam könnte man eher das Verhalten bei Zeichenketten nennen, die nur ASCII-Zeichen enthalten. Das wird so gemacht um Speicher zu sparen und weil man ASCII-Zeichenketten problemlos mit Unicode-Objekten "mischen" kann. Denn die können im Bedarfsfall ohne Fehler automatisch in Unicode-Objekte umegewandelt werden.
Du machst irgendwo etwas fundamental falsch, denn die gezeigten Quelltextschnippsel können nicht zu dem behaupteten Ergebnis führen.
Code: Alles auswählen
In [571]: import xml.etree.cElementTree as ETree
In [572]: text = ETree.Element('text')
In [573]: text.text = u'Niederl\xe4ndisch'
In [574]: ETree.tostring(text)
Out[574]: '<text>Niederländisch</text>'
Zeig mal bitte ein minimales Beispiel wie Du da ``<text>u'Niederl\xe4ndisch'</text>`` herausbekommen haben willst ohne irgendwann mal `repr()` die Daten anzuwenden.
@Dauerbaustelle: Ich habe nichts von HTML erzählt. Schon gar nichts was HTML-Parser hier irgendwie ins Spiel gebracht hätte.
Re: Lesen und Schreiben von kvtml Vokabeldateien
Verfasst: Dienstag 11. Mai 2010, 22:49
von Ubuntuxer
Uups, entschuldige ich hab da irgendetwas durcheinandergebracht.
Also es sieht bei mir so aus:
Orginal:
<name>Niederländisch</name>
Bei u'Niederl\xe4ndisch':
<name>Niederländisch</name>
Bei 'Niederl\xc3\xa4ndisch': (u'Niederl\xe4ndisch'.encode('utf-8'))
<name>Niederländisch</name>
Re: Lesen und Schreiben von kvtml Vokabeldateien
Verfasst: Mittwoch 12. Mai 2010, 00:21
von BlackJack
@Ubuntuxer: Und wo liegt jetzt das Problem? ``<name>Niederländisch</name>`` ist gültiges XML das genau das gewünschte darstellt.
Re: Lesen und Schreiben von kvtml Vokabeldateien
Verfasst: Mittwoch 12. Mai 2010, 12:01
von Ubuntuxer
BlackJack hat geschrieben:@Ubuntuxer: Und wo liegt jetzt das Problem? ``<name>Niederländisch</name>`` ist gültiges XML das genau das gewünschte darstellt.
Ich habe gerade gemerkt, dass das tatsächlich ohne Probleme funktioniert.
Parley konnte meine erstellte Datei aus einem anderen Grund nicht lesen. Anscheinend werden die Dateien von Parley irgendwie gecacht, sodass wenn ich die erstellte Datei ohne die beiden ersten Zeilen öffne und danach die Zeilen einfüge und noch einmal die Datei mit Parley öffne nur eine Sprache angezeigt wird. Ich dachte die ganze Zeit dies läge an den Unicodes, da die deutschen Wörter in Parley nicht angezeigt wurden.
Damit hat sich das Unicode Problem erledigt. Danke für deine Geduld Blackjack.
Hat einer noch eine Idee wie ich das Problem mit den ersten beiden Zeilen lösen kann?
Re: Lesen und Schreiben von kvtml Vokabeldateien
Verfasst: Mittwoch 12. Mai 2010, 12:02
von Hyperion
Ubuntuxer hat geschrieben:
Hat einer noch eine Idee wie ich das Problem mit den ersten beiden Zeilen lösen kann?
Hast Du meinen Post überlesen?
Re: Lesen und Schreiben von kvtml Vokabeldateien
Verfasst: Mittwoch 12. Mai 2010, 15:10
von Ubuntuxer
Hyperion hat geschrieben:Ubuntuxer hat geschrieben:
Hat einer noch eine Idee wie ich das Problem mit den ersten beiden Zeilen lösen kann?
Hast Du meinen Post überlesen?
Ich möchte den Doctype nicht auslesen, sondern in eine neue kvtml Datei reinschreiben. Mit lxml kann man zumindestens den Doctype auslesen, aber ich habe mir auch die lxml Referenz angeschaut und keine Erklärung gefunden wie man den Doctype in eine neue xml schreiben kann.
Code: Alles auswählen
from lxml import etree
root = etree.Element("kvtml")
root.set("version", "2.0")
tree = etree.ElementTree(root)
tree.docinfo.doctype = u'<!DOCTYPE kvtml PUBLIC "kvtml2.dtd" "http://edu.kde.org/kvtml/kvtml2.dtd">'
AttributeError: attribute 'doctype' of 'lxml.etree.DocInfo' objects is not writable