You are close. You will need to reiterate through any element that contains the name G
once you find the name G
. So you will want to use something more along these lines (which uses iteration rather than xpath or find, per your requirements):
>>> def remove(name, value, root):
"""
Iterates through the @root element and removes elements
where the @name != @value.
"""
for element in root:
if element.attrib.get(name) != value:
root.remove(element)
>>> def remove_siblings_of(name, value, root):
"""
Recursively removes from the @root element all elements which (1) do
not have @name == @value but (2) do have a sibling where @name == @value.
"""
for element in root:
if element.attrib.get(name) == value:
remove(name, value, root) # need to reiterate through element now to remove previous siblings
if len(element):
remove_siblings_of(name, value, element)
return root
When you use the latter function on your xml, you will get the result you are looking for:
>>> siblings_removed = remove_siblings_of('name', 'G', root)
>>> print et.tostring(siblings_removed)
<xml>
<letter name="A">
<letter name="B">
<letter name="G">
</letter>
</letter>
<letter name="E">
<letter name="F">
</letter>
</letter>
</letter>
</xml>