2016-06-24 3 views
1

Wie entferne ich in Python einen Knoten, aber behalte seine Kinder mit xml.etree API?Python xml.etree - Knoten entfernen, aber Kinder behalten (Kinder zu Großeltern zuweisen)

Ja, ich weiß, dass es eine answer using lxml gibt, aber da Teil der Python-Website ist, denke ich, dass es auch eine Antwort verdient.

Original-XML-Datei:

<?xml version="1.0"?> 
<data> 
    <country name="Liechtenstein"> 
     <rank>1</rank> 
     <year>2008</year> 
     <gdppc>141100</gdppc> 
     <neighbor name="Austria" direction="E"/> 
     <neighbor name="Switzerland" direction="W"/> 
    </country> 
    <country name="Singapore"> 
     <rank>4</rank> 
     <year>2011</year> 
     <gdppc>59900</gdppc> 
     <neighbor name="Malaysia" direction="N"/> 
    </country> 
    <country name="Panama"> 
     <rank>68</rank> 
     <year>2011</year> 
     <gdppc>13600</gdppc> 
     <neighbor name="Costa Rica" direction="W"/> 
     <neighbor name="Colombia" direction="E"/> 
    </country> 
</data> 

Sagen wir, ich country Knoten entfernen möchten, aber die Kinder zu halten und sie an die Eltern von country zuweisen?

Idealerweise möchte ich eine Lösung, die "Dinge an Ort und Stelle" macht, anstatt einen neuen Baum zu erstellen.

My (ohne Funktion) Lösung:

# Get all parents of `country` 
for country_parent in root.findall(".//country/.."): 
    print(country_parent.tag) 
    # Some countries could have same parent so get all 
    # `country` nodes of current parent 
    for country in country_parent.findall("./country"): 
     print('\t', country.tag) 
     # For each child of `country`, assign it to parent 
     # and then delete it from `parent` 
     for country_child in country: 
      print('\t\t', country_child.tag) 
      country_parent.append(country_child) 
      country.remove(country_child) 
     country_parent.remove(country) 
tree.write("test_mod.xml") 

Ausgabe meines Druck Aussagen:

data 
    country 
     rank 
     gdppc 
     neighbor 
    country 
     rank 
     gdppc 
    country 
     rank 
     gdppc 
     neighbor 

Sogleich können wir sehen, dass es ein Problem: country den Tag year fehlen und einige neighbor Tags.

Die resultierende .xml Ausgabe:

<data> 
    <rank>1</rank> 
     <gdppc>141100</gdppc> 
     <neighbor direction="W" name="Switzerland" /> 
    <rank>4</rank> 
     <gdppc>59900</gdppc> 
     <rank>68</rank> 
     <gdppc>13600</gdppc> 
     <neighbor direction="E" name="Colombia" /> 
    </data> 

Dies ist offensichtlich falsch.

FRAGE: Warum passiert das?

Ich kann mir vorstellen, es ist von der Anhängen/Entfernen etwas mit der Liste zu brechen, d. H. Ich habe die Liste "ungültig" ähnlich Iterator.

+0

'für country_child in country [:]:' wie in der Antwort zu Ihrer letzten Frage, http://stackoverflow.com/questions/37702011/removing-an-element-from-a-parsed-xml- Baumstörung-Iteration –

Antwort

1

Entfernen Sie diese Zeile aus Ihrem Programm:

 country.remove(country_child) 

Die Iteration eines xml.etree.ElementTree.Element im wesentlichen bis zum list von Unterelementen übergeben. Das Ändern dieser Liste während der Iteration führt zu ungeraden Ergebnissen.

+0

Warum bricht diese Linie die Dinge? – Adrian

+0

Ich überprüfe das jetzt. Ich glaube, es ist aus dem Grund, den Sie vermutet haben, dass Sie die Liste modifizieren, während Sie darüber iterieren. –

+0

aber es ist eine "Liste" von Elementen, kein Iterator, oder? – Adrian

Verwandte Themen