Seite 1 von 2
aus XML-Datei Daten ausgelesen - nun neue reinschreiben
Verfasst: Donnerstag 17. Juli 2008, 08:41
von Daniela
Hallo alle miteinander,
ich muss mal wieder eure Hilfe in Anspruch nehmen. Diesmal zum Thema XML. Ich habe eine XML-Datei die automatisch durch ein anderes Programm geschrieben wird. Nun will ich diese Datei mit Hilfe von Python erweitern.
Also konkret soll zum Einen ein neuer Unterpunkt erstellt werden und zum Anderen ein völlig neuer Zweig erstellt werden mit deren Unterpunkten.
Hier mal die XML-Datei die bisher da ist:
Code: Alles auswählen
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE roadmap SYSTEM "roadmap.dtd">
<roadmap version="1.2">
<stations>
<station angle="0" id="id0" name="Station1">
<point x="-5000" y="4042"/>
</station>
<station angle="0" id="id1" name="Station2">
<point x="5050" y="3927"/>
</station>
<station angle="0" id="id2" name="Station3">
<point x="-8000" y="-1996"/>
</station>
Hier soll eine neue Station eingefügt werden, nach oberem Muster
</stations>
Hier soll nun folgendes eingefügt werden:
<edges>
<edge endstation="id3" startstation="id0">
<points>
<point x="-5000" y="4042"/>
....
</points>
</edge>
</edges>
</roadmap>
Den Anfang des „Station-Tags“ kann man so übernehmen, dass heißt
Die x- und y-Werte werden durch ein Tupel ausgelesen in der Form:
Stationspunkt = (2569, 4859)
Dieser Punkt wird durch verschiedenste Berechnungen im Vorfeld ermittelt.
Danach geht es weiter mit dem Einlesen einer Liste und abspeichern in dem XML-File. Die Liste hat n-Elemente (und jeweils in Tupeln) und jedes einzelne soll in ein Tag gepackt werden.
Die Beispielliste sieht so aus:
Code: Alles auswählen
Liste = [(2016, 1986), (6095, 4526), (6359, 4102), (2280, 1562), (2544, 1138)]
Ich hab mich auch schon ein bisschen in xml mit python eingelesen, aber ich weiß im Moment nicht so richtig, wo ich anfangen soll, bzw. welche Module am besten geeignet sind, ob dom/minidom, elementtree, sax etc.
Ausgeparst wird die XML-Datei übrigens über Elementtree. Das ausparsen wurde benötigt, um bestimmte Berechnungen durchzuführen. Und nun sollen die Ergebnisse der Berchnungen zurück in die XML-Datei geschrieben werden.
Das ganze wurde so gelöst:
Code: Alles auswählen
from xml.etree import ElementTree as etree
def auslesen_Punkte():
doc = etree.parse('leichteBerechnung.rm')
for station in doc.findall('stations/station'):
point = station.find('point')
result.append((station.get('id'),
(int(point.get('x')), int(point.get('y')))))
return result
Für Hinweise und Ratschläge wäre ich sehr dankbar.
LG
Daniela
Verfasst: Donnerstag 17. Juli 2008, 12:31
von Leonidas
Hast du dir die ElementTree-API angesehen? Es ist letztendlich ganz einfach, daher werde ich hier keine Lösung posten, denn es bringt dir mehr wenn du dir die Doku durchliest und dann im Interaktiven Interpreter mittels ElementTree selbst eine XML-Datei zusammensetzt. Dann wirst du sehen wie es funktioniert und kannst dir dann deine Frage selbst beantworten.
Verfasst: Donnerstag 17. Juli 2008, 16:03
von Hyperion
Zumal Du ja in letzter Zeit viele Beiträge zum Thema XML gestellt hast

(Und iirc lief es dabei schon mehrfach auf ElementTree hinaus)
Verfasst: Freitag 18. Juli 2008, 12:07
von Daniela
Also ich hab mich in elementtree eingelesen, hab aber dazu noch ein paar Fragen.
Wenn ich neue Unterelemente erstellt hab, wie kann ich diesen dann Attribute hinzufügen, genauer gesagt aus einer Liste einen Wert zuweisen.
Ich hab unter anderem die
API mir durchgelesen, aber nichts passendes gefunden, oder ich hab es überlesen.
Code: Alles auswählen
station = etree.SubElement(stations, "station", angle="0", id="id3", name="Station4")
stpoint = etree.SubElement(station, "point", x="", y="")
dort sollen nun in den Anführungszeichen von x und y Zahlen reingeschrieben werden. Mir würde ja schon ein allgemeines Beispiel zur Veranschaulichung reichen, damit ich verstehe, was da gemacht wird.
LG
Daniela
Verfasst: Freitag 18. Juli 2008, 12:15
von Leonidas
Dir scheinen Grundkenntnise zu fehlen:
Code: Alles auswählen
from xml.etree import ElementTree as ET
e1 = ET.Element('root')
zahl = 12
e2 = ET.SubElement(e1, "child", x=str(zahl))
ET.dump(e1)
Verfasst: Freitag 18. Juli 2008, 12:17
von Hyperion
Daniela hat geschrieben:
dort sollen nun in den Anführungszeichen von x und y Zahlen reingeschrieben werden. Mir würde ja schon ein allgemeines Beispiel zur Veranschaulichung reichen, damit ich verstehe, was da gemacht wird.
Was meinst Du mit reinschreiben? So was?
Code: Alles auswählen
x = 6
y = 7
stpoint = etree.SubElement(station, "point", x="%d" % x, y="%d" % y)
Verfasst: Freitag 18. Juli 2008, 13:00
von Daniela
Joah, das meinte ich mit reinschreiben.
Wenn ich jetzt beides mal zusammenfasse, krieg ich irgendwie ne komische ausgabe:
So sieht es bisher aus:
Code: Alles auswählen
from xml.etree import ElementTree as etree
letzterPunkt = 12 # hab ich jetzt mal vereinfacht!
doc = open("leichteBerechnung.rm", "rw")
tree = etree.parse(doc)
root = tree.getroot()
stations = tree.getroot().find("stations")
station = etree.SubElement(stations, "station", angle="0", id="id3", name="Station4")
stpoint = etree.SubElement(station, "point", x="%d" % letzterPunkt) #, y=str(letzterPunkt)[1])
etree.dump(root)
So und das kommt dann danach raus:
Code: Alles auswählen
gekürzt,
<station angle="0" id="id3" name="Station4">
<point x="(" y="3" />
</station>
<station angle="0" id="id3" name="Station4">
<point x="1" />
</station>
<station angle="0" id="id3" name="Station4">
<point x="12" />
</station>
<station angle="0" id="id3" name="Station4">
<point x="12" />
</station>
<station angle="0" id="id3" name="Station4">
<point x="12" />
</station>
<station angle="0" id="id3" name="Station4">
<point x="12" />
</station>
<station angle="0" id="id3" name="Station4">
<point x="12" />
</station>
<station angle="0" id="id3" name="Station4">
<point x="12" />
</station></stations>
</roadmap>
Interessant hierbei ist ja jetzt, das es mehrfach (8-mal) aufgerufen wird, und das erst beim 3. Mal der richtige Wert drinsteht. Und wie durch ein Wunder taucht beim ersten point-Attribut auch noch ein "y" auf, obwohl es gar nicht festgelegt wurde.
Ist doch komisch.
Verfasst: Freitag 18. Juli 2008, 13:10
von BlackJack
Leider einer von den Fällen, wo man sagen muss: Das glaube ich Dir nicht. Bitte ein minimales und lauffähiges Beispiel zeigen, das den Fehler aufweist und das man nachvollziehen kann.
Ansonsten muss das Problem irgendwo in Quelltext liegen, den Du uns nicht zeigst. Zum Beispiel kann bei ``x="%d" % letzterPunkt`` niemals eine geöffnete Klammer heraus kommen.
Verfasst: Freitag 18. Juli 2008, 13:22
von Hyperion
Kann es sein, dass Du die Datei ständig erweiterst und nicht neu anlegst? Das könnte erklären, wieso da ggf. Fragmente von früheren Versuchen drinstehen.
Verfasst: Freitag 18. Juli 2008, 13:31
von Daniela
BlackJack hat geschrieben:
Ansonsten muss das Problem irgendwo in Quelltext liegen, den Du uns nicht zeigst. Zum Beispiel kann bei ``x="%d" % letzterPunkt`` niemals eine geöffnete Klammer heraus kommen.
Das war mir auch klar, deshalb hatte ich mich ja gewundert.
Jedenfalls nach einiger Zeit warten, ist das Problem jetzt behoben. Es wird das als Attribut angefügt, was auch rein soll.
Ich hatte übrigens alles an Quellcode in meinem Post reinkopiert! Nur den Anfang der XML-Datei hatte ich gekürzt, weil da stand sowieso nur das drin, was ich im allerersten Posting reinkopiert hatte. Daran hat sich in der Zwischenzeit auch nichts verändert gehabt.
Naja dann kann ich ja weitermachen.
Trotzdem Danke für eure Hilfe.
Daniela
Verfasst: Freitag 18. Juli 2008, 13:41
von Leonidas
Daniela hat geschrieben:Jedenfalls nach einiger Zeit warten, ist das Problem jetzt behoben. Es wird das als Attribut angefügt, was auch rein soll.
Warten? Musste der Code erst reifen?
Verfasst: Freitag 18. Juli 2008, 13:45
von BlackJack
@Daniela: Der Quelltext und die Beschreibung passen nicht zusammen. Im Quelltext wird nichts 8-mal aufgerufen und der Quelltext selbst verändert nichts an der Datei, d.h. wenn man den 8-mal startet wird an der XML-Datei nichts geändert und nur die letzte <station> ist die hinzugefügte. Die 7 davor müssen schon in der XML-Datei vorhanden gewesen sein.
Verfasst: Freitag 18. Juli 2008, 13:45
von Daniela
Nein, aber ich hab zwischenzeitlich was anderes gemacht, noch ein bisschen zu XML und so gelesen und dann hab ich es nochmal ausprobiert und auf einmal ging es.
Das meinte ich mit warten. Vielleicht hätte ich Unterbrechung oder so schreiben sollen....
@BlackJack:
kann eigentlich nicht sein, denn ich hab nach jedem Versuch das was ich nicht mehr brauchte aus der Datei immer wieder gelöscht (per hand).
Verfasst: Freitag 18. Juli 2008, 14:04
von BlackJack
In dem gezeigten Quelltext wird das veränderte XML nun mal nicht gespeichert, wie soll sich die Datei dann bitte ändern?
Verfasst: Montag 21. Juli 2008, 13:51
von Daniela
Das es letztlich in die Datei geschrieben wurde, kann daran gelegen haben, dass ich zwischenzeitlich den write-Befehl geschrieben hatte und dann aukommentiert hatte und dann irgendwann wieder "aktiviert" (Kommentarzeichen weggenommen) habe. Beim späteren Durchlaufen des Skiptes aber noch im Glauben war, dass der write-Befehl inaktiv ist.
Jedenfalls funktioniert mein Skript jetzt fast so, wie ich es haben will. Aus einer Liste mit Tupeln werden mir die Inhalte der Tupel jetzt in die vorgesehenen Stellen geschrieben.
Code: Alles auswählen
for k in xrange(0, len(punkt_liste), 1):
point = etree.SubElement(points, "point", x="%d" % punkt_liste[k][0], y="%d" % punkt_liste[k][1])
hier soll als x-wert der 1. Wert im Tupel genommen werden und als y-wert der 2. Wert des Tupels genommen werden.
Nur wenn ich es ausführe, bekomme ich folgedes :
Code: Alles auswählen
<point x="2016" y="2016" /><point x="6095" y="6095" /><point x="6359" y="6359" /><point x="2280" y="2280" /><point x="2544" y="2544" />
So sehen die Tupel eigentlich aus:
Code: Alles auswählen
[(2016, 1986), (6095, 4526), (6359, 4102), (2280, 1562), (2544, 1138),
Das sind aber jeweils nur die X-Koordinaten, die Y-Koordinaten fehlen. Kann mir vielleicht jemand sagen, wie auch bei der Y-Koordinate der richtige Wert eingefügt werden kann.
Daniela
EDIT:
Hat sich erledigt. Es funktioniert jetzt, so wie ich es haben will. weiß auch nicht, warum vorher die falschen WErte bei y angegeben wurden.
Auf einmal funktioniert es!
Verfasst: Montag 21. Juli 2008, 15:12
von BlackJack
Bitte die Schleife vereinfachen. Das ist Python und nicht C, Pascal, oder eine andere Sprache wo man für so etwas einen Index braucht.
Code: Alles auswählen
for x, y in punkt_liste:
point = etree.SubElement(points, 'point', x='%d' % x, y='%d' % y)
Verfasst: Montag 21. Juli 2008, 15:16
von Daniela
Na dann werd ich das machen.
Nur ich hatte es so schon ein paar mal im Forum gesehen und dachte, dass es passen würde.
Und wie kann ich jetzt die Ausgabe so hinbekommen, dass alles vernünftig verschachtelt ist, ohne dass alles in eine Zeile geschrieben wird. Also so dass eine lesbare XML-Struktur entsteht?
Verfasst: Montag 21. Juli 2008, 15:32
von Zap
Daniela hat geschrieben:Und wie kann ich jetzt die Ausgabe so hinbekommen, dass alles vernünftig verschachtelt ist, ohne dass alles in eine Zeile geschrieben wird. Also so dass eine lesbare XML-Struktur entsteht?
Die Frage hatte ich auch schonmal gestellt
http://www.python-forum.de/topic-11945.html
Verfasst: Montag 21. Juli 2008, 15:35
von Daniela
Danke für den hinweis
Verfasst: Dienstag 22. Juli 2008, 09:21
von Daniela
Ich muss nochmal kurz stören.
Bei elementtree gibt es ja eigentlich eine Funktion namens "Comment", nur wenn ich jetzt diese nutzen will, um einen Kommentar zu verfassen für meine XML-Datei, wird der Kommentar aber gar nicht in die Datei geschrieben.
Muss man da noch irgendwas besonderes beachten? Bisher hab ich das so geschrieben:
Code: Alles auswählen
kommentar = etree.Comment("DOCTYPE roadmap SYSTEM \"roadmap.dtd\"")
Ohne doppelte Anführungsstriche kommt ein Fehler, mit einfachen Apostrophen wird das auch nichts. Der Kommentar soll gleich in der 2. Zeile stehen, gleich hinter der "Versions und Kodierungs-Zeile", also diese proceeding instruction.
Ich hab mir auch schon
diesen Beitrag durchgelesen, aber ich will mir ja keine Liste vorher erstellen, sondern gleich beim Schreiben der Datei einen Kommentar mit einfügen.
Danke schonmal
LG
Daniela