grundsaetzliche Frage zu ElementTree

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
shakebox
User
Beiträge: 175
Registriert: Montag 31. März 2008, 17:01

Hi!

Ich bin noch in meinen Anfangsschritten mit Python. Von daher haben sich manche Konzepte und Ideen noch nicht wirklich verinnerlicht bzw. ich steh mir manchmal halt selbst im Weg.

Meine Aufgabe ist momentan, aus einer Filemaker-Datenbank mittels XML-Publishing Daten auszulesen, diese zu parsen und dann die geparsten Daten neu zu verwursten und in ein neues XML-File zu schreiben. Den ersten Teil (Abfragen und Parsen von Filemaker) hab ich mit dem tollen Modul fmkr.py http://www.lfd.uci.edu/~gohlke/code/fmkr.py.html hingekriegt. Mit diesen Daten kann ich jetzt auch schoene Sachen machen.

Was mir jetzt fehlt, ist daraus ein neues XML-File zu erzeugen. Ich hab mir da mal ElementTree angeschaut, das klingt recht gut und einfach. Nur haengt es bei mir momentan an einer Stelle voellig am Grundverstaendnis:

mein Ziel-XML hat ungefaehr folgende Struktur:

Code: Alles auswählen

<root>
  <general>
    <tag1>wert1</tag1>
  </general>
  <timeline>
    <tag2>wert2</tag2>
    <tag3>wert3</tag3>
  </timeline>
<root>
Soweit einfach und ueberschaubar. Das Element 'general' kommt im Ziel nur 1x vor. Das ist einfach. Das Element 'timeline' dagegen kommt mehrfach vor, je nachdem wieviele Eintraege ich in der Filemaker-Datenbank gerade abhaengig von der Abfrage bekomme.

Wie erzeuge ich jetzt vom Prinzip her mehrere solche timeline-Elemente, ohne genau zu wissen wieviele es werden. Denn eigentlich wuerde ich ja ganz am Ende gerne einfach ein

Code: Alles auswählen

print etree.tostring(root)
machen koennen und bekomme dann meine komplette Struktur mit 1 mal general und eben n mal timeline.

Hoffe ich hab mein Problem halbwegs verstaendlich formuliert, sonst sagt mir bitte Bescheid, ich tu mir da grad ein wenig schwer das auszudruecken.

Danke und lieben Gruss, Shakebox
shakebox
User
Beiträge: 175
Registriert: Montag 31. März 2008, 17:01

vielleicht doch noch naeher zu dem was ich nicht ganz verstehe, sonst kann vielleicht niemand meinen Knoten im Hirn nachvollziehen:

bei dem Elementtree leg ich ja fuer alle Elemente ne neue "Variable" an, bzw. genauer ein "Objekt" (oder?).

Also z.B. eben so:

Code: Alles auswählen

root = etree.Element('root')
general = etree.SubElement(root, 'general')
tag1 = etree.SubElement(general, 'wert1')
Aber wie mach ich da jetzt innerhalb einer Schleife dann mehrere SubElemente timeline? Also sowas:

Code: Alles auswählen

for i in FilemakerDatensaetze:
    xy = etree.SubElement(root, 'timeline')
    xytag_xy = etree.SubElement(xy, 'tag2')
mir ist es grad nicht so ganz klar wie ich da diese xy und xytag_xy durchnummeriere, weil ich die ja nicht alle gleich nennen kann.

Vermutlich ganz einfach, aber ich kapier es grad nicht.
Benutzeravatar
helduel
User
Beiträge: 300
Registriert: Montag 23. Juli 2007, 14:05
Wohnort: Laupheim

shakebox hat geschrieben:mir ist es grad nicht so ganz klar wie ich da diese xy und xytag_xy durchnummeriere, weil ich die ja nicht alle gleich nennen kann.
Doch, das kannst du ;-). So, wie du es hast, müsste es eigentlich klappen. Lediglich, wenn du die tags durchnumerierst, musst du natürlich noch einen Zähler hinzufügen, aber das sollte ja kein großes Problem sein:

Code: Alles auswählen

# mal davon ausgegangen, dass FilemakerDatensaetze eine Liste mit irgendwelchen Daten ist
for i, row in enumerate(FilemakerDatensaetze):
    xy = etree.SubElement(root, 'timeline')
    xytag_xy = etree.SubElement(xy, 'tag%i' % i+1) # i+1 -> bei 1 anfangen, nicht bei 0
Das erzeugt dir unter root jeweils ein timeline-Element und ein tag-Element. Da du aber durchaus mehrere tag-Elemente pro timeline-Element brauchst, musst du die tag-Elemente wiederum mittels einer Schleife erzeugen. Wie das genau geht, kommt auf deine Daten an. Aber vielleicht reicht dir ja diese Hilfestellung?

SubElement erzeugt ein neues Objekt im angegebenen Parent - in deinem Fall root. Nachdem (!) es das getan hat, gibt es dir das Objekt zurück, damit du ggf. gleich noch etwas damit anstellen kannst (z. B. Elemente darunter hinzufügen), aber das ist kein Muss. Also nicht verwirren lassen, wenn nach jedem Schleifendurchgang ein anderes Objekt an deine Namen xy und xytag_xy gebunden werden - das ist schlichtweg Wurst.
shakebox
User
Beiträge: 175
Registriert: Montag 31. März 2008, 17:01

oh weia, danke. Da haett ich doch besser den Code den ich hier als 'Idee' gepostet habe auch einfach mal ausprobieren sollen :)

Ich bin da deshalb gestolpert weil ich ein kleines Script habe (xml2tree.py), das mit dem XMLTreeBuilder ein XML zerlegt und ein Script bastelt das andersrum dann alle Elementgenerierungs-Aufrufe beinhaltet, um das reingefuetterte XML wieder reproduzieren zu koennen. Und da in meinem Beispielscript mehrere timeline-Elemente drin waren, hat er da nicht automatisch ne for-Schleife draus gemacht sondern die fleissig timeline1, timeline2, usw. genannt. Deshalb dachte ich, ich muesste da fuer jedes Timeline-Element ne eigene Zeile mit nem eigenen Variablen-Namen erzeugen.

Danke vielmals, so komme ich weiter. An diese Objekt-Denkweise werd ich mich noch schwer gewoehnen muessen. Wenn man bisher eigentlich nur Shell-Scripting gemacht ist das schon etwas fremd, aber geil! ;-)
BlackJack

Wobei die Tagnamen hoffentlich nur in dem Beispiel nummeriert sind. Das ist nämlich kein guter Stil. Entweder reicht die Position des Knotens, die ist ja auch eindeutig, oder man benutzt dafür ein Attribut.
shakebox
User
Beiträge: 175
Registriert: Montag 31. März 2008, 17:01

Du meinst in meinem Codeschnipsel? Ja, das hab ich nur fuer das Beispiel gemacht. Die eigentlichen Tags heissen anders, ohne Zahlen.

Von daher brauch ich auch den counter i nirgends ausser eben zum bilden der Schleife.
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

shakebox hat geschrieben:Von daher brauch ich auch den counter i nirgends ausser eben zum bilden der Schleife.
Dafür brauchst du keinen Counter in Python.

Code: Alles auswählen

for row in FilemakerDatensaetze:
    xy = etree.SubElement(root, 'timeline')
    xytag_xy = etree.SubElement(xy, 'tag')
shakebox
User
Beiträge: 175
Registriert: Montag 31. März 2008, 17:01

jein :) "Counter" war natuerlich der falsche Begriff, der passt bei Python da nicht. Aber ich hab das "i" ja genauso verwendet wie Du "row". Das Objekt meinte ich.
Antworten