我有一个以下的xml文档:
<node0>
<node1>
<node2 a1="x1"> ... </node2>
<node2 a1="x2"> ... </node2>
<node2 a1="x1"> ... </node2>
</node1>
</node0>
我想在node2
时过滤掉a1="x2"
。用户提供需要测试和过滤掉的xpath和属性值。我在像BeautifulSoup这样的python中查看了一些解决方案,但它们太复杂了,不保留文本的大小写。我希望保留文档与以前一样过滤掉一些东西。
您能推荐一个简单而简洁的解决方案吗?从它的外观来看,这不应该太复杂。实际的xml文档并不像上面那么简单,但想法是一样的。
答案 0 :(得分:6)
这使用标准库中的xml.etree.ElementTree
:
import xml.etree.ElementTree as xee
data='''\
<node1>
<node2 a1="x1"> ... </node2>
<node2 a1="x2"> ... </node2>
<node2 a1="x1"> ... </node2>
</node1>
'''
doc=xee.fromstring(data)
for tag in doc.findall('node2'):
if tag.attrib['a1']=='x2':
doc.remove(tag)
print(xee.tostring(doc))
# <node1>
# <node2 a1="x1"> ... </node2>
# <node2 a1="x1"> ... </node2>
# </node1>
这使用lxml
,它不在标准库中,但有a more powerful syntax:
import lxml.etree
data='''\
<node1>
<node2 a1="x1"> ... </node2>
<node2 a1="x2"> ... </node2>
<node2 a1="x1"> ... </node2>
</node1>
'''
doc = lxml.etree.XML(data)
e=doc.find('node2/[@a1="x2"]')
doc.remove(e)
print(lxml.etree.tostring(doc))
# <node1>
# <node2 a1="x1"> ... </node2>
# <node2 a1="x1"> ... </node2>
# </node1>
修改:如果node2
更深入地隐藏在xml中,那么您可以遍历所有标记,检查每个父标记以查看node2
元素是否为其中一个孩子,如果是这样的话就将其删除:
仅使用xml.etree.ElementTree:
doc=xee.fromstring(data)
for parent in doc.getiterator():
for child in parent.findall('node2'):
if child.attrib['a1']=='x2':
parent.remove(child)
使用lxml:
doc = lxml.etree.XML(data)
for parent in doc.iter('*'):
child=parent.find('node2/[@a1="x2"]')
if child is not None:
parent.remove(child)