как удалить элемент в 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 63

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
       )