我有一个XML文档,我想在其中搜索某些元素,如果它们符合某些条件 我想删除它们
但是,我似乎无法访问该元素的父级,以便我可以将其删除
file = open('test.xml', "r")
elem = ElementTree.parse(file)
namespace = "{http://somens}"
props = elem.findall('.//{0}prop'.format(namespace))
for prop in props:
type = prop.attrib.get('type', None)
if type == 'json':
value = json.loads(prop.attrib['value'])
if value['name'] == 'Page1.Button1':
#here I need to access the parent of prop
# in order to delete the prop
我有办法做到这一点吗?
由于
答案 0 :(得分:20)
您可以使用相应的remove
方法删除子元素。要删除元素,您必须调用其父remove
方法。遗憾的是Element
没有提供对其父母的引用,因此您需要跟踪父/子关系(这与您对elem.findall()
的使用有关)
建议的解决方案可能如下所示:
root = elem.getroot()
for child in root:
if child.name != "prop":
continue
if True:# TODO: do your check here!
root.remove(child)
PS:不要使用prop.attrib.get()
,请使用prop.get()
,如here所述。
答案 1 :(得分:2)
您可以使用xpath选择Element的父级。
file = open('test.xml', "r")
elem = ElementTree.parse(file)
namespace = "{http://somens}"
props = elem.findall('.//{0}prop'.format(namespace))
for prop in props:
type = prop.get('type', None)
if type == 'json':
value = json.loads(prop.attrib['value'])
if value['name'] == 'Page1.Button1':
# Get parent and remove this prop
parent = prop.find("..")
parent.remove(prop)
http://docs.python.org/2/library/xml.etree.elementtree.html#supported-xpath-syntax
,如果你尝试它不起作用:http://elmpowered.skawaii.net/?p=74
所以你必须:
file = open('test.xml', "r")
elem = ElementTree.parse(file)
namespace = "{http://somens}"
search = './/{0}prop'.format(namespace)
# Use xpath to get all parents of props
prop_parents = elem.findall(search + '/..')
for parent in prop_parents:
# Still have to find and iterate through child props
for prop in parent.findall(search):
type = prop.get('type', None)
if type == 'json':
value = json.loads(prop.attrib['value'])
if value['name'] == 'Page1.Button1':
parent.remove(prop)
这是两个搜索和一个嵌套循环。内部搜索仅在已知包含道具作为第一个子项的元素上,但根据您的模式,这可能并不重要。
答案 2 :(得分:0)
我知道这是一个老线程,但在我试图找出类似的任务时,这种情况一直在突然出现。由于两个原因,我不喜欢接受的答案:
1)它不处理多个嵌套级别的标签。
2)如果多个xml标签一个接一个地删除在同一级别,它将会中断。由于每个元素都是Element._children
的索引,因此在向前迭代时不应删除。
我认为这是一个更通用的解决方案:
import xml.etree.ElementTree as et
file = 'test.xml'
tree = et.parse(file)
root = tree.getroot()
def iterator(parents, nested=False):
for child in reversed(parents):
if nested:
if len(child) >= 1:
iterator(child)
if True: # Add your entire condition here
parents.remove(child)
iterator(root, nested=True)
对于OP,这应该有用 - 但我没有你正在使用的数据来测试它是否完美。
import xml.etree.ElementTree as et
file = 'test.xml'
tree = et.parse(file)
namespace = "{http://somens}"
props = tree.findall('.//{0}prop'.format(namespace))
def iterator(parents, nested=False):
for child in reversed(parents):
if nested:
if len(child) >= 1:
iterator(child)
if prop.attrib.get('type') == 'json':
value = json.loads(prop.attrib['value'])
if value['name'] == 'Page1.Button1':
parents.remove(child)
iterator(props, nested=True)
答案 3 :(得分:0)
我喜欢使用XPath表达式进行此类过滤。除非我不知道,否则必须在根级别应用这样的表达式,这意味着我不能只获取父级并在该父级上应用相同的表达式。但是,在我看来,只要没有所搜索的节点是根,就可以使用任何受支持的XPath,这是一个很好且灵活的解决方案。它是这样的:
root = elem.getroot()
# Find all nodes matching the filter string (flt)
nodes = root.findall(flt)
while len(nodes):
# As long as there are nodes, there should be parents
# Get the first of all parents to the found nodes
parent = root.findall(flt+'/..')[0]
# Use this parent to remove the first node
parent.remove(nodes[0])
# Find all remaining nodes
nodes = root.findall(flt)
答案 4 :(得分:0)
使用lxml模块的解决方案
from lxml import etree
root = ET.fromstring(xml_str)
for e in root.findall('.//{http://some.name.space}node'):
parent = e.getparent()
for child in parent.find('./{http://some.name.space}node'):
try:
parent.remove(child)
except ValueError:
pass