In XML Datei gezielt in einem Child suchen

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
himself
User
Beiträge: 5
Registriert: Montag 16. Januar 2017, 20:38

Hallo zusammen,

mein erster Post hier, ich hoffe ich mache alles richtig...
Mein Problem: Ich habe eine recht große XML Datei die eine Bauteil-liste, aber auch viele für mich nicht relevante Positionen enthält.
Ich möchte diese jetzt mittels eines python scripts durchsuchen und abspeichern.
Die ersten Schritte laufen schon, aber ich bekomme es nicht hin innerhalb eines childs nach einem Wert zu suchen.
Hier die xml:

Code: Alles auswählen

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
    <Teil id="id_1">
        <Part_number>11111</Part_number>
        <Description>Schraube</Description>
    </Teil>
	<Teil id="id_2">
        <Part_number>11112</Part_number>
        <Description>Mutter</Description>
    </Teil>
    <Baugruppe id="id_3">
        <Part_number>11113</Part_number>
        <Description>Irgendwas</Description>
    </Baugruppe>
    <Baugruppe id="id_4">
        <Part_number>11114</Part_number>
        <Description>Ganzwasanderes</Description>
    </Baugruppe>	
</root>	
Hier mein code:

Code: Alles auswählen

from xml.etree import ElementTree
data = 'path/to/Bauteile.xml'
save = 'path/to/output'
with open(data, 'rt') as f:
    tree = ElementTree.parse(f)
fobj = open(save, 'w')

Subgruppen = ['Teil', 'Baugruppe']
for n in Subgruppen:
    for node in tree.findall(n):
        id = node.attrib.get('id')
        for path in [ './/Part_number']:
            node = tree.find(path)
            Sachnummer = node.text
        for path in [ './/Description']:
            node = tree.find(path)
            Bezeichnung = node.text
        fobj.write(n + ';' + id + ';' + Sachnummer + ';' + Bezeichnung + ';' + '\n')
Die Ausgabe:
Teil id_1 11111 Schraube
Teil id_2 11111 Schraube
Baugruppe id_3 11111 Schraube
Baugruppe id_4 11111 Schraube
Und was da stehen sollte:
Teil id_1 11111 Schraube
Teil id_2 11112 Mutter
Baugruppe id_3 11113 Irgendwas
Baugruppe id_4 11114 Ganzwasanderes
Ich finde also die richtige ID, bin dann aber nicht in der Lage die restlichen Teile innerhalb dieses Child's durchzuführen.

Vielen Dank für die Hilfe!

Alfons
Zuletzt geändert von Anonymous am Montag 16. Januar 2017, 22:30, insgesamt 1-mal geändert.
Grund: Quelltext in Codebox-Tags gesetzt.
BlackJack

@himself: Wo denkst Du denn das Du im Kindknoten suchst, oder suchen solltest, und wo suchst Du stattdessen tatsächlich? Das ist ziemlich offensichtlich, wo der Fehler liegt.
Sirius3
User
Beiträge: 18299
Registriert: Sonntag 21. Oktober 2012, 17:20

@himself: statt der for-Schleifen über _ein_ Element würde man das ganze ohne for-Schleife schreiben, zumal innerhalb der Schleife eine konkrete Variable gefüllt wird. ElemenTree-Elemente kennen findtext, damit wird das heraussuchen der Sachnummer ein Einzeiler. n ist ein schlechter Variablenname für eine Subgruppe. ElementTree.parse kann auch mit Dateinamen umgehen. Üblicherweise schreibt man Variablennamen komplett klein. Wenn Du ;-separierte Dateien schreiben willst, nimm das passende Modul aus der Standardbibliothek: csv
himself
User
Beiträge: 5
Registriert: Montag 16. Januar 2017, 20:38

@blackJack:

Danke erstmal. Ich denke ich kann schon sagen wo der Fehler ist:

Code: Alles auswählen

for path in [ './/Part_number']:
Hier müsste ich das ganze irgendwie einschränken auf das jeweilige Child. Ich weiss aber nicht wie. Konnte bis jetzt nichts finden.
Sollte irgendwie so aussehen vermute ich:

Code: Alles auswählen

for node.path in [ './/Part_number']:
Vielleicht fehlt mir auch lediglich der richtige Suchbegriff um weiter zu kommen.

@Sirius3: Danke für den Hinweis. Das sind gerade meine ersten gehversuche mit python. grundsätzlich würde ich gerne optimieren aber zuerst würd ich es gern zum laufen bringen bzw. verstehen. Die Hinweise mit Variablennamen werde ich berücksichtigen. Das mit dem Dateinamen liegt daran dass ich auf 2 Systemen (Win und Linux) teste und nur auskommentiere, je nachdem wo ich gerade bin. Die Datei ist der letzte Schritt.

Danke auf jeden Fall dass ihr euch auch mit solchen Anfängerproblemen auseinandersetzt....

Gruß

himself
BlackJack

@himself: Der problematische Ausdruck ist ``tree.find(path)``. Du suchst nicht im Kindknoten sondern im gesamten Baum. An der Stelle muss `find()` statt auf dem gesamten Baum, nur auf dem Kindelement aufgerufen werden.
himself
User
Beiträge: 5
Registriert: Montag 16. Januar 2017, 20:38

@BlackJack: Danke das wars!
Sirius3
User
Beiträge: 18299
Registriert: Sonntag 21. Oktober 2012, 17:20

So könnte es aussehen:

Code: Alles auswählen

from csv import writer as csv_writer
from xml.etree import ElementTree

INPUT_FILENAME = 'path/to/Bauteile.xml'
OUTPUT_FILENAME = 'path/to/output.csv'
SUB_GROUPS = ['Teil', 'Baugruppe']

tree = ElementTree.parse(INPUT_FILENAME)
with open(OUTPUT_FILENAME, 'w') as output:
    writer = csv_writer(output, delimiter=';')
    for sub_group in SUB_GROUPS:
        for node in tree.findall(sub_group):
            id = node.attrib.get('id')
            part_number = node.findtext('Part_number')
            description = node.findtext('Description')
            writer.writerow([sub_group, id, part_number, description])
Antworten