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.
Daniela
User
Beiträge: 73
Registriert: Donnerstag 19. Juni 2008, 07:32

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

Code: Alles auswählen

<station angle ="0" id="id3" name="Station4">
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
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

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.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Zumal Du ja in letzter Zeit viele Beiträge zum Thema XML gestellt hast ;-) (Und iirc lief es dabei schon mehrfach auf ElementTree hinaus)
Daniela
User
Beiträge: 73
Registriert: Donnerstag 19. Juni 2008, 07:32

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

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)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

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)
Daniela
User
Beiträge: 73
Registriert: Donnerstag 19. Juni 2008, 07:32

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.
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.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

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.
Daniela
User
Beiträge: 73
Registriert: Donnerstag 19. Juni 2008, 07:32

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

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?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
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.
Daniela
User
Beiträge: 73
Registriert: Donnerstag 19. Juni 2008, 07:32

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

In dem gezeigten Quelltext wird das veränderte XML nun mal nicht gespeichert, wie soll sich die Datei dann bitte ändern?
Daniela
User
Beiträge: 73
Registriert: Donnerstag 19. Juni 2008, 07:32

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!
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)
Daniela
User
Beiträge: 73
Registriert: Donnerstag 19. Juni 2008, 07:32

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?
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

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
Daniela
User
Beiträge: 73
Registriert: Donnerstag 19. Juni 2008, 07:32

Danke für den hinweis
Daniela
User
Beiträge: 73
Registriert: Donnerstag 19. Juni 2008, 07:32

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
Antworten