Seite 1 von 1

Eintrag aus XML löschen

Verfasst: Samstag 19. März 2016, 17:06
von nathan6
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ß

Re: Eintrag aus XML löschen

Verfasst: Samstag 19. März 2016, 18:08
von Sirius3
@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)

Re: Eintrag aus XML löschen

Verfasst: Sonntag 20. März 2016, 02:28
von nathan6
Danke, funktioniert wunderbar.
Aber wenn ich damit jetzt zum Beispiel "root2" löschen will klappt es nicht. Was ist da jetzt der Unterschied?

Gruß

Re: Eintrag aus XML löschen

Verfasst: Sonntag 20. März 2016, 13:33
von nathan6
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

Re: Eintrag aus XML löschen

Verfasst: Sonntag 20. März 2016, 13:42
von BlackJack
@nathan6: Wie sieht denn der Code dazu aus? Was ist `parent` in diesem Fall?

Re: Eintrag aus XML löschen

Verfasst: Sonntag 20. März 2016, 13:54
von nathan6
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


Re: Eintrag aus XML löschen

Verfasst: Sonntag 20. März 2016, 14:16
von 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.

Re: Eintrag aus XML löschen

Verfasst: Montag 21. März 2016, 23:24
von nathan6
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

Re: Eintrag aus XML löschen

Verfasst: Dienstag 22. März 2016, 00:26
von 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.

Re: Eintrag aus XML löschen

Verfasst: Dienstag 22. März 2016, 00:56
von nathan6
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ß

Re: Eintrag aus XML löschen

Verfasst: Dienstag 22. März 2016, 01:02
von 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‽

Re: Eintrag aus XML löschen

Verfasst: Dienstag 22. März 2016, 01:13
von nathan6
Ä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.

Re: Eintrag aus XML löschen

Verfasst: Dienstag 22. März 2016, 08:39
von Sirius3
@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.

Re: Eintrag aus XML löschen

Verfasst: Dienstag 22. März 2016, 10:16
von nathan6
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