Hallo Forum,
ich möchte gerne einen code beautifier / pretty printer für Docbook XML schreiben.
Der Prozess sähe folgendermassen aus: Input ist ein in einem Standard-Texteditor handgeschriebenes, beliebig formatiertes, aber valides XML-Dokument, welches ein Subset der in Docbook definierten Elemente benutzt. Dieses Dokument wird vom pretty printer geparst und benutzerfreundlich formatiert nach std.out ausgegeben.
Ich habe bereits einen ersten Prototyp geschrieben, indem ich die Klasse HTMLParser aus dem Modul HTMLParser abgeleitet und entsprechend implementiert habe. Die Anregung dazu habe ich dem Buch "Python in a Nutshell" (2. Auflage, 2006) entnommen.
Bin mir jetzt nur nicht ganz sicher, ob ich mit HTMLParser den richtigen Ansatz gewählt habe. Gibt es eventuell zwischenzeitlich ein für meine Zwecke (Parsen von XML) eher geeignetes eventuell aktuelleres Modul/Klasse? Was würdet ihr empfehlen?
VG, beetronic
PS: Ich arbeite auf Ubuntu 10.04 mit Python 2.6.5.
Parsen von XML / pretty printing
@beetronic: In der Standardbibliothek gibt es `elementtree` und als externes Modul `lxml.etree` mit der gleichen API aber einigen nützlichen Erweiterungen. Beides steht Dir unter Ubuntu 10.04 über die Paketverwaltung zur Verfügung. (Und auch in älteren Versionen.)
Docbook ist kein HTML sondern XML. Daher ist ein HTMLParser falsch. lxml wurde schon erwähnt. Damit ist es relativ einfach, ein XML-Dokument umzuformatieren und zu "pretty-printen":
Wer möchte, kann auch noch method="c14n" angeben, dann wird nicht nur eine Repräsentation des XML-Infosets gewählt, sondern die canonische, bei der es feste Regeln gibt, wo Namensräume definiert und wie Attribute sortiert werden. Das ist wichtig, wenn man z.B. Prüfsummen (SHA256 oder so) berechnen will.
Stefan
Code: Alles auswählen
import lxml.etree as e
print e.tostring(e.fromstring("<a><b>foo</b></a>"), pretty_print=True)
Stefan
Nur der Vollständigkeit halber, um diesen Thread abzuschliessen; Vielen Dank für eure Anregungen. Ich habe mir ElementTree und lxml angesehen und mich dann aber doch für eine andere Variante entschieden, weil ich beide APIs für meine Zwecke als Overkill ansehen würde.
Habe jetzt den Expat Parser als Grundlage genommen (xml.parsers.expat) mit dem ich event-basiert mein XML parsen kann.
Habe nur leider keine Möglichkeit gefunden, Entities (&foo;) richtig zu verarbeiten, diese versucht der Parser immer aufzulösen, was ich eigentlich nicht will. Für mich würde es reichen, wenn Entities einfach unbesehen vom Input in den Output Stream kopiert würden. Ich habe mir jetzt damit geholfen, dass ich alle Entities vor dem Parsen maskiere (durch Ersetzen des Ampersand-Zeichens) und am Ende wieder demaskiere.
VG, bt
Habe jetzt den Expat Parser als Grundlage genommen (xml.parsers.expat) mit dem ich event-basiert mein XML parsen kann.
Habe nur leider keine Möglichkeit gefunden, Entities (&foo;) richtig zu verarbeiten, diese versucht der Parser immer aufzulösen, was ich eigentlich nicht will. Für mich würde es reichen, wenn Entities einfach unbesehen vom Input in den Output Stream kopiert würden. Ich habe mir jetzt damit geholfen, dass ich alle Entities vor dem Parsen maskiere (durch Ersetzen des Ampersand-Zeichens) und am Ende wieder demaskiere.
VG, bt
@beetronic: Entities müssen AFAIK vom Parser aufgelöst werden. Genauso darfst Du nicht erwarten, das CDATA-Abschnitte erhalten bleiben. Falls Du die Vorstellung hast so eine Umformatierung wäre einfach nur eine Operation auf einer Textdatei, solltest Du umdenken. Serialisiertes XML sollte man nicht als Textdatei betrachten und verarbeiten.
Zum "Overkill": `ElementTree.iterparse()` kann man auch zum ereignisbasierten Parsen verwenden.
Zum "Overkill": `ElementTree.iterparse()` kann man auch zum ereignisbasierten Parsen verwenden.