我需要使用python的lxml基于属性的内容完全删除元素.例:
import lxml.etree as et
xml="""
<groceries>
<fruit state="rotten">apple</fruit>
<fruit state="fresh">pear</fruit>
<fruit state="fresh">starfruit</fruit>
<fruit state="rotten">mango</fruit>
<fruit state="fresh">peach</fruit>
</groceries>
"""
tree=et.fromstring(xml)
for bad in tree.xpath("//fruit[@state=\'rotten\']"):
#remove this element from the tree
print et.tostring(tree, pretty_print=True)
Run Code Online (Sandbox Code Playgroud)
我想要打印:
<groceries>
<fruit state="fresh">pear</fruit>
<fruit state="fresh">starfruit</fruit>
<fruit state="fresh">peach</fruit>
</groceries>
Run Code Online (Sandbox Code Playgroud)
有没有办法在不存储临时变量并手动打印的情况下执行此操作,如下所示:
newxml="<groceries>\n"
for elt in tree.xpath('//fruit[@state=\'fresh\']'):
newxml+=et.tostring(elt)
newxml+="</groceries>"
Run Code Online (Sandbox Code Playgroud)
Céd*_*ien 138
使用removexmlElement 的方法:
tree=et.fromstring(xml)
for bad in tree.xpath("//fruit[@state=\'rotten\']"):
bad.getparent().remove(bad) # here I grab the parent of the element to call the remove directly on it
print et.tostring(tree, pretty_print=True, xml_declaration=True)
Run Code Online (Sandbox Code Playgroud)
如果我必须与@Acorn版本进行比较,即使要删除的元素不直接位于xml的根节点下,我的工作也会正常工作.
Aco*_*orn 28
你正在寻找这个remove功能.调用树的remove方法并传递一个子元素来删除.
import lxml.etree as et
xml="""
<groceries>
<fruit state="rotten">apple</fruit>
<fruit state="fresh">pear</fruit>
<punnet>
<fruit state="rotten">strawberry</fruit>
<fruit state="fresh">blueberry</fruit>
</punnet>
<fruit state="fresh">starfruit</fruit>
<fruit state="rotten">mango</fruit>
<fruit state="fresh">peach</fruit>
</groceries>
"""
tree=et.fromstring(xml)
for bad in tree.xpath("//fruit[@state='rotten']"):
bad.getparent().remove(bad)
print et.tostring(tree, pretty_print=True)
Run Code Online (Sandbox Code Playgroud)
结果:
<groceries>
<fruit state="fresh">pear</fruit>
<fruit state="fresh">starfruit</fruit>
<fruit state="fresh">peach</fruit>
</groceries>
Run Code Online (Sandbox Code Playgroud)
zep*_*hor 12
我遇到了一种情况:
<div>
<script>
some code
</script>
text here
</div>
Run Code Online (Sandbox Code Playgroud)
div.remove(script)将删除text here我不是故意的部分.
按照这里的答案,我发现etree.strip_elements对我来说这是一个更好的解决方案,你可以控制是否用with_tail=(bool)param 删除后面的文本.
但我仍然不知道这是否可以使用xpath过滤器标记.只是把它作为通知.
这是文档:
strip_elements(tree_or_element,*tag_names,with_tail = True)
使用树或子树中提供的标记名称删除所有元素.这将删除元素及其整个子树,包括其所有属性,文本内容和后代.除非您将
with_tail关键字参数选项显式设置为False,否则它还将删除元素的尾部文本.标记名称可以包含通配符,如
_Element.iter.请注意,即使匹配,也不会删除您传递的元素(或ElementTree根元素).它只会对待它的后代.如果要包含根元素,请在调用此函数之前直接检查其标记名称.
用法示例::
Run Code Online (Sandbox Code Playgroud)strip_elements(some_element, 'simpletagname', # non-namespaced tag '{http://some/ns}tagname', # namespaced tag '{http://some/other/ns}*' # any tag from a namespace lxml.etree.Comment # comments )
正如已经提到的,您可以使用该remove()方法从树中删除(子)元素:
for bad in tree.xpath("//fruit[@state=\'rotten\']"):
bad.getparent().remove(bad)
Run Code Online (Sandbox Code Playgroud)
但它会删除包括其 在内的元素tail,如果您正在处理 HTML 等混合内容文档,这会是一个问题:
<div><fruit state="rotten">avocado</fruit> Hello!</div>
Run Code Online (Sandbox Code Playgroud)
成为
<div></div>
Run Code Online (Sandbox Code Playgroud)
我想这就是你并不总是想要的:)我创建了辅助函数来仅删除元素并保留其尾部:
for bad in tree.xpath("//fruit[@state=\'rotten\']"):
bad.getparent().remove(bad)
Run Code Online (Sandbox Code Playgroud)
这样它将保留尾部文本:
<div> Hello!</div>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
49446 次 |
| 最近记录: |