aus XML-Datei Daten ausgelesen - nun neue reinschreiben

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.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Das der Kommentar nicht auftaucht ist ja nicht verwunderlich, denn du hast ihn ja auch nicht zum Tree hinzugefügt; der Kommentar ist also "freifliegend" - er weiß ja nicht mal zu welchem Baum er gehören sollte.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Daniela
User
Beiträge: 73
Registriert: Donnerstag 19. Juni 2008, 07:32

Klingt logisch, nur irgendwie weiß ich im Moment grad nicht, wo ich das anhängen soll.

Code: Alles auswählen

doc = open('datei.rm', 'rw')
tree = etree.parse(doc) # einlesen der vorhandenen XML-Datei
root = tree.getroot() # Bestimmung des Wurzelelements

stations = tree.getroot().find("stations") # erster Knoten wird ausgelesen

kommentar = etree.Comment("DOCTYPE roadmap SYSTEM \"roadmap.dtd\"") # wo muss der rangehängt werden?
...
tree = etree.ElementTree(root)
tree.write('datei.rm', encoding='UTF-8')
Irgendwie häng ich grad.

Daniela
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

Ich wüsste nur diese Lösung:

Code: Alles auswählen

In [16]: r = ET.Element("root")

In [17]: k = ET.Comment("Ich bin der Kommentar!")

In [18]: r.insert(0, k)

In [19]: ET.tostring(r)
Out[19]: '<root><!-- Ich bin der Kommentar! --></root>'
Daniela
User
Beiträge: 73
Registriert: Donnerstag 19. Juni 2008, 07:32

Danke dafür, es funktioniert.

wenn ich jetzt (noch) einen Docstring einfügen will, nach dem Muster

Code: Alles auswählen

<!DOCTYPE bla SYSTEM "keks.dtd">
würde ich das so machen:

Code: Alles auswählen

dockommentar = etree.XMLTreeBuilder.doctype('bla', 0, "keks.dtd")
Aber hier bekomme ich folgendes dann zurück:

Code: Alles auswählen

TypeError: unbound method doctype() must be called with XMLTreeBuilder instance as first argument (got str instance instead)
Wird der Docstring anders aufgerufen, bzw. die Klammern anders gefüllt? Ich hab mich an das gehalten, was in der API steht. Nur mit der "0" war ich mir nicht sicher. Eigentlich brauch ich die auch nicht.

Daniela
Daniela
User
Beiträge: 73
Registriert: Donnerstag 19. Juni 2008, 07:32

Das mit dem Kommentar einfügen funktioniert ja soweit, nur dummerweise hatte ich übersehen, dass in das was ich da einfügen will kein Kommentar ist, sondern "Doctype-Deklaration".

im Elementtree-Modul gibt es ja die XML-TreeBuilder Objekte und mit diesem scheint man eigene Doctypes erstellen zu können, nur stellt sich für mich hier die Frage wie.
Denn die allgemeine Syntax sieht ja folgendes vor:

Code: Alles auswählen

doctype(name, pubid, system)
    #Handles a doctype declaration. name is the doctype name. pubid is the public identifier. system is the system identifier. 
Nur ich muss in meiner Datei nur einen Namen und das System angeben, ohne die "pubid".
Ich hab hier auch im Forum schon gelesen, dass solche Konstrukte "per Hand" eingefügt werden sollen/sollten. Nur kann ich mir nicht wirklich vorstellen, dass das so gut sein soll.

Gibt es irgendwie die Möglichkeit die Zeile entweder gleich aus der bestehenden Datei mit auszulesen, und dann in eine neue Datei mit reinzuschreiben, oder aber so in die neu zuschreibende Datei einfügen, dass es hinter der Kodierungszeile ist, aber vor der Wurzel des XML-Baums?

Danke schonmal für eure Hinweise

Daniela
Daniela
User
Beiträge: 73
Registriert: Donnerstag 19. Juni 2008, 07:32

So ich hab mich jetzt mal daran versucht, das zu befolgen, was Y0Gi (vor einer Weile) geschrieben hat zu befolgen:
Y0Gi hat geschrieben:Mit ET kannst du einfach ein neues `Element` anlegen und das als Root verwenden, indem du einfach `SubElement`e dranhängst. Über das Root-Element wandelst du abschließend das Dokument in einen String um (mit der Funktion `tostring`)
Hab ich gemacht. mein komplettes XML-dokument ist nun in einem String

Code: Alles auswählen

wurzel = etree.tostring(root)
Y0Gi hat geschrieben:und kannst dann über normale String-Konkatenation den gewünschten Header davor setzen.
String-Konkatenation ist doch eigentlich nur das Verknüpfen 2er Strings mit einem "+"-Zeichen, oder???
Ich hab aber auch noch die Methode ``concat`` im Modul ``Operator`` gefunden, welche ja das gleiche Ergebniss liefert. Oder bin ich jetzt auf dem Holzweg.
Jedenfalls durch diese Verknüpfung (entweder +-Zeichen, oder conat-Methode) ist nun der Header mit entsprechender DOCTYPE-Anweisung/Deklaration in einem String gespeichert.

Code: Alles auswählen

zsgf = header + baum
Wie kriege ich jetzt diesen (langen) String in eine Datei geschrieben/gespeichert?



Sorry übrigends für mein Dreifach-Posting, aber ich arbeite mich eben langsam an die Lösung ran.

Für Hinweise oder Vorschläge wäre ich sehr dankbar.

Daniela
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Daniela hat geschrieben:

Code: Alles auswählen

dockommentar = etree.XMLTreeBuilder.doctype('bla', 0, "keks.dtd")
Aber hier bekomme ich folgendes dann zurück:

Code: Alles auswählen

TypeError: unbound method doctype() must be called with XMLTreeBuilder instance as first argument (got str instance instead)
Lies noch einmal die Fehlermeldung und dann mach mal folgendes:

Code: Alles auswählen

print etree.XMLTreeBuilder
print etree.XMLTreeBuilder()
Fällt dir etwas auf?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Daniela hat geschrieben:
Y0Gi hat geschrieben:und kannst dann über normale String-Konkatenation den gewünschten Header davor setzen.
String-Konkatenation ist doch eigentlich nur das Verknüpfen 2er Strings mit einem "+"-Zeichen, oder???
Ich hab aber auch noch die Methode ``concat`` im Modul ``Operator`` gefunden, welche ja das gleiche Ergebniss liefert. Oder bin ich jetzt auf dem Holzweg.
Jein. Die Funktionen die in ``operator`` definiert sind, sind eigentlich nicht dafür gedacht direkt aufgerufen zu werden, dafür gibt es ja die normalen Operatoren. Sie sind vielmehr dazu gedacht in partielle Funktionen oder als Funktionen höherer Ordnung verwendet zu werden; sie direkt zu verwenden geht ist aber unnötig kompliziert.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Daniela
User
Beiträge: 73
Registriert: Donnerstag 19. Juni 2008, 07:32

DasIch hat geschrieben:Lies noch einmal die Fehlermeldung und dann mach mal folgendes:

Code: Alles auswählen

print etree.XMLTreeBuilder
print etree.XMLTreeBuilder()
Fällt dir etwas auf?
Ja, ich hab nie mit der Instanz gearbeitet. :oops:

Was ich aber trotzdem bei der Deklarierung von doctype nicht verstehe, ist dieser "public identifier". Besteht dieser einfach aus einer Zahl, Zeichenkette, oder sonst was? Was muss man angeben, wenn man ihn eigentlich nicht haben will/braucht? Irgendwas muss man ja angeben, sonst kommt folgendes zurück:

Code: Alles auswählen

dockommentar = etree.XMLTreeBuilder().doctype('bla', "keks.dtd") 
TypeError: doctype() takes exactly 4 arguments (3 given)
Das noch ein Argument benötigt wird, ist mir wenn ich das lese auch klar, aber was ist, wenn ich es in dem letztlichen Ergebniss (in der XML-Datei) nicht benötige?

Bisher hab ich es so geschrieben:

Code: Alles auswählen

dockommentar = etree.XMLTreeBuilder().doctype('bla', "public", "keks.dtd")
Wie wird jetzt diese Zeile in die Datei eingefügt, VOR dem Wurzelelement, aber NACH der Kodierungszeile?
Denn nach dem Schema von Zap funktioniert es nicht.

Code: Alles auswählen

dockommentar = etree.XMLTreeBuilder().doctype('bla','public', "keks.dtd") 
etree.insert(0, dockommentar)
etree.tostring(root)
Da wird dann gesagt:

Code: Alles auswählen

AttributeError: 'module' object has no attribute 'insert'
Und wie dann, ich meine wie bekomme ich jetzt diesen docstring in die XML rein, und dann noch an die richtige Stelle?

@Leonidas

gut zu wissen. Danke für den Hinweis


Daniela
Antworten