Parsen von XML / pretty printing

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
beetronic
User
Beiträge: 33
Registriert: Mittwoch 2. Mai 2007, 10:23

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.
BlackJack

@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.)
thomas15
User
Beiträge: 98
Registriert: Montag 7. April 2008, 19:07

hi beetronic,

aus eigener erfahrung kann ich lxml empfehlen da es auch xpath und xquery ermoeglicht. gute lib...
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

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":

Code: Alles auswählen

import lxml.etree as e
print e.tostring(e.fromstring("<a><b>foo</b></a>"), pretty_print=True)
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
beetronic
User
Beiträge: 33
Registriert: Mittwoch 2. Mai 2007, 10:23

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
BlackJack

@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.
Antworten