joemamah24
joemamah24

Reputation: 35

Implementing remove function for element tree element

I am trying to remove an element from an XML tree. My attempt is based on the example that I found in the Python documentation:

for country in root.findall('country'):
    # using root.findall() to avoid removal during traversal
    rank = int(country.find('rank').text)
    if rank > 50:
        root.remove(country)

tree.write('output.xml')

But I'm trying to use the remove() function for a string attribute, not an integer one.

for country in root.findall('country'):
    # using root.findall() to avoid removal during traversal
    description = country.find('rank').text
    root.remove(description)
    
tree.write('SampleData.xml')

But I get the following error:

TypeError: remove() argument must be xml.etree.ElementTree.Element, not str.

I ultimately added another element under country called description which holds a short description of the country and its features:

<data>
    <country name="Liechtenstein">
        <rank>1</rank>
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Austria" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
        <description>Liechtenstein has a lot of flowers.</description>
    </country>
    <country name="Singapore">
        <rank>4</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N" />
        <description>Singapore has a lot of street markets</description>
    </country>
    <country name="Panama">
        <rank>68</rank>
        <year>2011</year>
        <gdppc>13600</gdppc>
        <neighbor name="Costa Rica" direction="W" />
        <neighbor name="Colombia" direction="E" />
        <description>Panama is predominantly Spanish speaking.</description>
    </country>
</data>

I'm trying to use the remove() function to delete that description attribute for all instances.

Upvotes: 0

Views: 84

Answers (1)

trincot
trincot

Reputation: 351369

Indeed, in your code you are passing a string as argument, not a node:

    description = country.find('rank').text
    root.remove(description)

This is not what happens in the correct examples. The one with the integer does this:

    rank = int(country.find('rank').text)
    if rank > 50:
        root.remove(country)

Note that country is removed (a node), not rank (an int).

It is not clear what you want to do with the description, but make sure to remove a node, not a string. For instance,

    description = country.find('rank').text
    if description == "delete this":  # just an example condition
        root.remove(country)

Or, if you just want to remove the "rank" node and keep the country node:

    ranknode = country.find('rank')
    if ranknode.text == "delete this":
        country.remove(ranknode)

As you mention you have actually a description element (you call it an attribute, but that is confusing), you can target that element instead of rank:

    descriptionnode = country.find('description')
    if descriptionnode.text == "delete this":
        country.remove(descriptionnode)

Upvotes: 1

Related Questions