Удалите один элемент в lxml - PullRequest
1 голос
/ 01 мая 2020

Мне нужно удалить элемент XML при сохранении его данных. Функция l xml strip_tags удаляет элементы, но работает рекурсивно, и я хочу удалить один элемент.

Я попытался использовать ответ в этом сообщении , но remove удаляет весь элемент.

xml="""
<groceries>
  One <fruit state="rotten">apple</fruit> a day keeps the doctor away.
  This <fruit state="fresh">pear</fruit> is fresh.
</groceries>
"""

tree=ET.fromstring(xml)

for bad in tree.xpath("//fruit[@state='rotten']"):
    bad.getparent().remove(bad)

print (ET.tostring(tree, pretty_print=True))

Я хочу получить

<groceries>
    One apple a day keeps the doctor away.
    This <fruit state="fresh">pear</fruit> is fresh.
</groceries>\n'

Я получаю

<groceries>
    This <fruit state="fresh">pear</fruit> is fresh.
</groceries>\n'

Я пытался использовать strip_tags:

for bad in tree.xpath("//fruit[@state='rotten']"):
    ET.strip_tags(bad.getparent(), bad.tag)

<groceries>
    One apple a day keeps the doctor away.
    This pear is fresh.
</groceries>

Но это все лишает, и я просто хочу лишить элемент с помощью state='rotten'.

1 Ответ

1 голос
/ 01 мая 2020

Возможно, у кого-то есть идея получше, но это возможный обходной путь:

bad = tree.xpath(".//fruit[@state='rotten']")[0] #for simplicity, I didn't bother with a for loop in this case
txt = bad.text+bad.tail # collect the text content of bad; strangely enough it's not just 'apple'
bad.getparent().text += txt # add the collected text to the parent's existing text
tree.remove(bad) # this gets rid only of this specific 'bad'
print(etree.tostring(tree).decode())

Вывод:

<groceries>
  One apple a day keeps the doctor away.
  This <fruit state="fresh">pear</fruit> is fresh.
</groceries>
...