0

I have an xml file loaded, from which I want to remove elements that have no attributes or children, I'm trying to achieve something like this:

for child in root.find('targetElement'):
    print(child)
    if(len(child.attrib) < 1 and len(child) < 1):
        root.remove(child)

But I guess the problem is that I'm finding the element then trying to remove it from the root element. Can someone please tell me how to do this?

mao
  • 1,059
  • 2
  • 23
  • 43

1 Answers1

2

You need to remove a node from its parent, not from the root.

The following code works for lxml.etree:

from lxml import etree as ET

root = ET.parse('yourfile.xml')

for child in root.iterfind('targetElement'):
    if(len(child.attrib) < 1 and len(child) < 1):
        child.getparent().remove(child)

The standard xml.etree.ElementTree lacks any decent method of selecting the parent node. We can work around this limitation by constructing a child-to-parent map for the entire tree (source):

import xml.etree.ElementTree as ET

root = ET.parse('yourfile.xml')

# https://stackoverflow.com/a/20132342/18771
parent_map = {c:p for p in root.iter() for c in p}

for child in root.iterfind('targetElement'):
    if(len(child.attrib) < 1 and len(child) < 1):
        parent_map[child].remove(child)
Community
  • 1
  • 1
Tomalak
  • 332,285
  • 67
  • 532
  • 628
  • Sorry, what am I missing? AttributeError: 'xml.etree.ElementTree.Element' object has no attribute 'getparent' – mao Jul 20 '16 at 17:36
  • `getparent()` is available in lxml, but not in the standard library ElementTree module. – mzjn Jul 20 '16 at 17:48
  • @mao I see. Try `child.findall('..')[0].remove(child)`. – Tomalak Jul 20 '16 at 18:00
  • thanks but another issue child.findall('..')[0].remove(child) IndexError: list index out of range – mao Jul 20 '16 at 21:12
  • @mao It seems support for selecting the parent node in elementtree is more broken than I thought. Look at the modified answer. Also note that I use `iterfind()` instead of `find()` – Tomalak Jul 21 '16 at 06:04
  • I'm voting to downvote this question because the answer doesn't work. – Hamish Gibson Jun 20 '23 at 18:05