как удалить элемент в lxml
мне нужно полностью удалить элементы, основанные на содержимом атрибута, используя lxml python. Пример:
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)
Я хотел бы это напечатать:
<groceries>
<fruit state="fresh">pear</fruit>
<fruit state="fresh">starfruit</fruit>
<fruit state="fresh">peach</fruit>
</groceries>
есть ли способ сделать это без сохранения временной переменной и печать его вручную, как это:
newxml="<groceries>n"
for elt in tree.xpath('//fruit[@state='fresh']'):
newxml+=et.tostring(elt)
newxml+="</groceries>"
3 ответов
использовать remove
метод xmlElement:
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)
Если бы мне пришлось сравнивать с версией @Acorn, моя будет работать, даже если элементы для удаления не находятся непосредственно под корневым узлом вашего xml.
Я встретил одну ситуацию:
<div>
<script>
some code
</script>
text here
</div>
div.remove(script)
удалить text here
часть, которую я не хотел.
после ответа здесь, я обнаружил, что etree.strip_elements
является лучшим решением для меня, которое вы можете контролировать, будете ли вы удалять текст позади с with_tail=(bool)
парам.
но все же я не знаю, Может ли это использовать фильтр xpath для тега. Просто поставьте это для информирования.
вот док:
strip_elements (tree_or_element, *tag_names, with_tail=True)
удалить все элементы с указанными именами тегов из дерева или поддерево. Это приведет к удалению элементов и всего их поддерева, включая все их атрибуты, текстовое содержимое и потомков. Он также будет удален хвостовой текст элемента, если вы явно установите
with_tail
параметр аргумента ключевого слова False.имена тегов могут содержать подстановочные знаки, как в
_Element.iter
.обратите внимание, что это не удалит элемент (или корень ElementTree элемент), который вы прошли, даже если он соответствует. Это будет только лечить его потомок. Если вы хотите включить корневой элемент, проверьте его имя тега непосредственно перед вызовом этой функции.
пример использования::
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 )