ElementTree und XML Fragen

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

MoR4euZ hat geschrieben:ok hast recht root.ids war nur ein verzweifelter versuch von mir ;)
Du solltest nicht verzweifelt etwas versuchen, das nennt man "programming by accident", sondern verstehen was Du da tust.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from xml.etree import ElementTree as etree

xmldoc = 'process.xml'
new_runtime = 11.111111111 

f = file(xmldoc, 'r')
s = f.read()
root, id = etree.XMLID(s)

doc = etree.ElementTree(file=xmldoc)
doc.getroot()
rtime = id['1'].getchildren()[3]
rtime.clear()
rtime.text = new_runtime

doc.write(file=xmldoc)
f.close()
Du bindest den Namen `xmldoc` an den Dateinamen. Dann öffnest Du die Datei zum lesen und liest sie komplett ein. Den Dateiinhalt parst Du mit `XMLID()` und erhältst das Wurzelelement, mit allem was da dran hängt, und ein Dictionary das ID-Namen direkt auf die entsprechenden `Element`-Objekte abbildet.

Dann erzeugst Du mit `ElementTree()` *noch* einmal eine Objekthierarchie von `Element`-Objekten und bindest diese an den Namen `doc`. Davon ermittelst Du das Wurzelelement und machst nichts damit. Aber auch so wirklich gar nichts, nicht mal an einen Namen binden.

Dann holst Du Dir via ID ein `Element`-Objekt aus dem *ersten* Baum den Du eingelesen hast, löscht dessen Inhalt und setzt den Text auf die neue Laufzeit.

Und zum Schluss schreibst Du den Baum, den Du *nicht* verändert hast, wieder in eine Datei zurück und schliesst die Datei die die ganze Zeit über noch zum Lesen geöffnet war. Dabei kann nichts passieren wenn Du danach nicht wieder versuchst was zu lesen, aber es ist mindestens unsauber die so lange ohne Grund offen zu halten.
Benutzeravatar
MoR4euZ
User
Beiträge: 34
Registriert: Mittwoch 18. Oktober 2006, 21:21
Wohnort: Essen
Kontaktdaten:

BlackJack hat geschrieben:
MoR4euZ hat geschrieben:ok hast recht root.ids war nur ein verzweifelter versuch von mir ;)
Du solltest nicht verzweifelt etwas versuchen, das nennt man "programming by accident", sondern verstehen was Du da tust.
nett gesagt :)
so ist es :(
oder auch "try and error" genannt

ich will das entlich gelöst bekommen koste es was es wolle :evil:
danach lese ich auch braff mein python buch zuende ;)
noch habe ich genug motivation für das try and error verfahren
aber sicher nicht mehr lange hrhr

ich habe alles nochmal durchgedacht

Code: Alles auswählen

from xml.etree import ElementTree as etree

xmldoc = 'process.xml'
new_runtime = 99.111111111 

# Lesen
f = file(xmldoc, 'r')
s = f.read()
doc, id = etree.XMLID(s)
f.close()

# Voher
print 'RunTime vorher: ', id['1'].getchildren()[3].text #11.999999999
print 'RunTime Baum vorher:', s #11.999999999

# Veraendern
## Element verändern
id['1'].getchildren()[3].text = new_runtime
## Verändertes Element in Baum schreiben???
## mit etree.ElementTree(?) ???

# Nachher
print 'RunTime nachher: ', id['1'].getchildren()[3].text #99.111111111
print 'RunTime Baum nachher:', s #99.111111111 ist leider immernoch 11.999999999

# Schreiben
f = file(xmldoc, 'w')
f.write(s)
f.close()
das runtime element bekomme ich verändert aber ich bekomme das veränderte runtime element nicht in den baum (s) zurück geschrieben

das müstte doch mit etree.ElementTree() gehen oder nicht?
ich komme leider immer noch nicht drauf wie :(

stimmt sonst alles andere?

gute nacht
BlackJack

Stimmt ja schon fast. `s` ist an die Zeichenkette gebunden, die Du am Anfang eingelesen hast. Die veränderst Du nicht, Du veränderst ein `Element`-Objekt in der Objekthierarchie die an den Namen `doc` gebunden ist. Und genau diese musst Du in eine Datei schreiben, nachdem Du sie verändert hast.

Da `doc` an ein `Element`-Objekt gebunden ist, welches keine `write()`-Methode hat, musst Du dieses Element in einen `ElementTree` stecken und auf dem dann die `write()`-Methode aufrufen. Das war's dann auch schon.
Benutzeravatar
MoR4euZ
User
Beiträge: 34
Registriert: Mittwoch 18. Oktober 2006, 21:21
Wohnort: Essen
Kontaktdaten:

ja habs
DANKE! :)

ich hoffe es ist alles richtig

ein manko hat die sache allerdings noch :?

die ersten beiden zeilen in der xmldatei (über dem roottag 'Process_db') fehlen nach dem schreiben

'doc' kennt doch das roottag oder nicht?

habe mir noch mal getroot() genauer angesehen
aber eine lösung habe ich bis jetzt nicht gefunden

Code: Alles auswählen

import os
import time
from decimal import Decimal as deci
from xml.etree import ElementTree as etree

xmldoc = './xml/process.xml'

#read xmldoc
f = file(xmldoc, 'r')
s = f.read()
doc, id = etree.XMLID(s)
f.close()

#read path
path = id['1'].getchildren()[2].text

#start programm (with path) and detect runtime
start_time = time.time()
os.system(path)
runtime = time.time() - start_time

#runtime addition
old_runtime = id['1'].getchildren()[4].text 
new_runtime = deci(str(runtime)) + deci(old_runtime) 

#change RunTime element
id['1'].getchildren()[4].text = str(new_runtime)

#print
print 'ermittelte RunTime: ', runtime
print 'alte RunTime: ', old_runtime 
print 'neue RunTime: ', new_runtime

#write new_runtime
new_doc = etree.ElementTree(doc)
f = file(xmldoc, 'w')
new_doc.write(f)
f.close()
morgen verbaue ich alles schön sauber in funktionen und lese beim pythonbuch weiter ;)
BlackJack

MoR4euZ hat geschrieben:ein manko hat die sache allerdings noch :?

die ersten beiden zeilen in der xmldatei (über dem roottag 'Process_db') fehlen nach dem schreiben

'doc' kennt doch das roottag oder nicht?
`doc` ist an das Element, das den Wurzelknoten repräsentiert gebunden. Die XML Deklaration und die "processing instruction" liegen aber ausserhalb des Baums.

Die XML Deklaration schreibt `ElementTree` nur wenn eine andere Kodierung als ASCII oder UTF-8 gewählt wurde. Nur dann benötigt man sie unbedingt, sonst ist sie optional.

Ansonsten wirft `ElementTree` "processing instructions" und Kommentare beim einlesen weg. Da gibt's zwei Lösungen. Einmal eine mit `ElementTree` vom Author selbst: http://www.effbot.org/zone/element-pi.htm

Oder Du benutzt das `lxml` Paket. Das hat eine `ElementTree`-kompatible API und behält auch "processing instructions" und Kommentare im Baum. Die ausserhalb des Baums "überleben" aber anscheinend nur wenn man die `tostring()` Funktion auf Modulebene verwendet.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

BlackJack hat geschrieben:Da gibt's zwei Lösungen.
HI!

Hier habe ich noch eine Lösung: :wink:

Code: Alles auswählen

import codecs

xmldoc = './xml/process.xml'

# Kopfzeilen auslesen
f = codecs.open(xmldoc, "rU", "utf-8")
head_lines = []
for line in f:
    if line.lstrip().startswith("<?"):
        head_lines.append(line)
    else:
        break
f.close()


# Hier wird gearbeitet...
# Hier wird gearbeitet...


# Kopfzeilen wieder rein schreiben
f = codecs.open(xmldoc, "r+", "utf-8")
xml = f.read()
f.seek(0)
f.truncate(0)
f.writelines(head_lines)
f.write(xml)
f.close()
lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Antworten