Eintrag aus XML löschen

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
nathan6
User
Beiträge: 17
Registriert: Montag 7. September 2015, 17:25

Hallo,

Ich versuche verzweifelt einen Eintrag aus einer XML Datei zu löschen, klappt aber irgendwie nicht. Ich benutze etree.

Code: Alles auswählen

<root>
	<root2>
		<cost value="1" />
		<sell money="0" />
   <root2/>
<root/>

Code: Alles auswählen

    def mod(self):
        tree = ET.parse('test.xml')
        root7 = tree.getroot()
        for child in root7.iter('sell'):
           root7.remove(child.get)

Kann mir einer nen Tipp verpassen ? Bin noch recht neu dabei.

Gruß
Sirius3
User
Beiträge: 17753
Registriert: Sonntag 21. Oktober 2012, 17:20

@nathan6: child.get ist eine Methode, wie soll man denn die aus irgendeiner Liste löschen können? Zudem mußt Du das Element aus dem Elternelement löschen, bei Dir also root2:

Code: Alles auswählen

for parent in tree.iterfind('.//sell/..'):
    for child in parent.iter('sell'):
        parent.remove(child)
nathan6
User
Beiträge: 17
Registriert: Montag 7. September 2015, 17:25

Danke, funktioniert wunderbar.
Aber wenn ich damit jetzt zum Beispiel "root2" löschen will klappt es nicht. Was ist da jetzt der Unterschied?

Gruß
nathan6
User
Beiträge: 17
Registriert: Montag 7. September 2015, 17:25

Er findet zwar root2' at 0x1633ed0 ist aber nicht in der list ?
Das ist sehr verwirrend.

Code: Alles auswählen

<Element 'root2' at 0x1633ed0>
Traceback (most recent call last):
  File "test.py", line 174, in <module>
    func()
  File "test.py", line 117, in mod
    parent.remove(child)
  File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 337, in remove
    self._children.remove(element)
ValueError: list.remove(x): x not in list
None
Zuletzt geändert von nathan6 am Sonntag 20. März 2016, 13:55, insgesamt 1-mal geändert.
BlackJack

@nathan6: Wie sieht denn der Code dazu aus? Was ist `parent` in diesem Fall?
nathan6
User
Beiträge: 17
Registriert: Montag 7. September 2015, 17:25

Ich hab einfach "Sell" mit "root2" ausgetauscht.

Code: Alles auswählen

        for parent in tree.iterfind('.//root2/..'):
             for child in parent.iter('root2'):
                 print child
                 parent.remove(child) 

Code: Alles auswählen

<Element 'root2' at 0x2428ed0>
<Element 'root2' at 0x242b690>
<Element 'root2' at 0x242b790>
<Element 'root2' at 0x242bc90>
<Element 'root2' at 0x242be10>
Traceback (most recent call last):
  File "test.py", line 170, in <module>
    func()
  File "test.py", line 113, in mod
    parent.remove(child)
  File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 337, in remove
    self._children.remove(element)
ValueError: list.remove(x): x not in list
None

BlackJack

@nathan6: Du entfernst da Kindelemente aus einem Element während Du über diese Kindelemente iterierst, das funktioniert so nicht. Damit sägst Du an dem Ast auf dem Du sitzt. Du musst vorher eine Liste aller (zu löschenden) Kindelemente erstellen über die Du dann iterieren kannst um sie zu löschen. Also benutz dafür keine Methode die ”lazy” über die Elemente iteriert und sucht, sondern eine die Dir schon eine Liste mit allen Treffern liefert.
nathan6
User
Beiträge: 17
Registriert: Montag 7. September 2015, 17:25

Also ich hab jetzt eine Liste mit allen zu löschenden Kinderelementen(root2) erstellt. Aber egal was ich versuche ich bekomm es nicht gelöscht. Das XML ist wirklich sehr verwirrend für mich.

Code: Alles auswählen

<root>
...
	<root1>
	...
		<root2>
			<Cost money="0"/>
			<Sell money="0"/>
			...
		</root2>
	</root1>
</root>

        root = lxml.etree.parse('xml/test.xml')
        mylist = root.xpath('.//root1/root2')

So und nun muss ich alles was in der Liste ist aus dem Elternverzeichnis löschen.
Also:

Code: Alles auswählen

        for parent in root.iterfind('.//root1/..'):
            for child in parent.iter(mylist):
                parent.remove(child)
In php ist das alles viel einfacher :K
BlackJack

@nathan6: Was soll denn ``for child in parent.iter(mylist):`` bewirken? Ich würde auch nicht unbedingt mit ``/..`` im XPath-Ausdruck arbeiten sondern mir erst einmal das Elternelement suchen aus dem Du die Kindelemente löschen möchtest. Diese zweite Aufgabe ist ja schliesslich etwas anders als das erste. Hier sind die zu löschenden Elemente alle im gleichen Elternelement.

XML ist auch in PHP nicht einfacher. Es ist vielleicht einfacher sich für PHP eine unsaubere Lösung zu ergooglen die man dann verwenden kann ohne sie zu verstehen. Dadurch wird die Materie an sich aber nicht einfacher.
nathan6
User
Beiträge: 17
Registriert: Montag 7. September 2015, 17:25

Naja hab in den letzten 6 std in denen ich versucht habe es zu verstehen, 7 mal Nasenbluten bekommen.
Und in php ist es verständlicher aufgebaut:

Code: Alles auswählen

    $RootXML = simplexml_load_file($xmlFile);  
    foreach($BRootXML->root1 as $root) { 
		unset($root->root2); 
    $RootXML->asXML($t1);
aber ich hab mir jetzt einfach ne Schleife geschrieben, so funktioniert es für mich auch.

Code: Alles auswählen

        root = lxml.etree.parse('xml/test.xml')
        mylist = root.xpath('.//root2')
        lon = len(mylist)
        kil = 0
        while lon > kil:
           for parent in root.iterfind('.//root2/..'):
               for child in parent.iterfind('root2'):
                   parent.remove(child)
                   kil = kil + 1

        root.write('xml/test.xml')
Gruß
BlackJack

@nathan6: Ähm, und warum gehst Du in Python nicht genau so vor wie in PHP? Vielleicht weil Du nicht wirklich verstanden hast was Du da machst? Weder in PHP noch in Python‽
nathan6
User
Beiträge: 17
Registriert: Montag 7. September 2015, 17:25

Ähm wer stellt den nun die Fragen an wen ?
Ich bin nunmal hier weil ich nicht weiß wie ich das in Python umsetzen kann, weil ich keine Erfahrung mit Python habe, bis jetzt.
Sirius3
User
Beiträge: 17753
Registriert: Sonntag 21. Oktober 2012, 17:20

@nathan6: ein Weg, etwas zu lernen, ist es sich selbst Gedanken zu machen. Wenn Du schon eine Lösung in PHP hast, warum setzt Du sie dann nicht so auch mit Python um? Die Schwierigkeit bei Deiner ersten Frage war ja, dass nicht klar war, dass die Struktur des XML immer gleich aussieht, so dass man tatsächlich vom Kind-Element zum Eltern-Element zurückgehen muß, wobei ElementTree kein parent kennt. Daher der Umweg. In PHP gehst Du aber den direkten Weg, von root1 nach root2. Das kannst Du natürlich so auch mit Python machen. findall und remove kennst Du ja schon, und das ist ja auch ausreichend.
nathan6
User
Beiträge: 17
Registriert: Montag 7. September 2015, 17:25

Sirius3 hat geschrieben:@nathan6: ein Weg, etwas zu lernen, ist es sich selbst Gedanken zu machen. Wenn Du schon eine Lösung in PHP hast, warum setzt Du sie dann nicht so auch mit Python um? Die Schwierigkeit bei Deiner ersten Frage war ja, dass nicht klar war, dass die Struktur des XML immer gleich aussieht, so dass man tatsächlich vom Kind-Element zum Eltern-Element zurückgehen muß, wobei ElementTree kein parent kennt. Daher der Umweg. In PHP gehst Du aber den direkten Weg, von root1 nach root2. Das kannst Du natürlich so auch mit Python machen. findall und remove kennst Du ja schon, und das ist ja auch ausreichend.
Danke, deine Antwort hat mir tatsächlich weitergeholfen :D
Antworten