Удаление элемента, но не текста после него
У меня есть XML
файл похож на этот:
<root>
<a>Some <b>bad</b> text <i>that</i> I <u>do <i>not</i></u> want to keep.</a>
</root>
Я хочу удалить весь текст в <b>
или же <u>
элементы (и потомки), а остальные выведите. Вот что я попробовал:
from __future__ import print_function
import xml.etree.ElementTree as ET
tree = ET.parse('a.xml')
root = tree.getroot()
parent_map = {c:p for p in root.iter() for c in p}
for item in root.findall('.//b'):
parent_map[item].remove(item)
for item in root.findall('.//u'):
parent_map[item].remove(item)
print(''.join(root.itertext()).strip())
(Я использовал рецепт в этом ответе, чтобы построить parent_map
). Проблема, конечно, в том, что с remove(item)
Я также удаляю текст после элемента, и результат:
Some that I
тогда как я хочу:
Some text that I want to keep.
Есть ли решение?
1 ответ
Решение
Если вы не будете использовать что-то лучше, вы можете использовать clear()
вместо remove()
сохраняя хвост элемента:
import xml.etree.ElementTree as ET
data = """<root>
<a>Some <b>bad</b> text <i>that</i> I <u>do <i>not</i></u> want to keep.</a>
</root>"""
tree = ET.fromstring(data)
a = tree.find('a')
for element in a:
if element.tag in ('b', 'u'):
tail = element.tail
element.clear()
element.tail = tail
print ET.tostring(tree)
печать (см. пустой b
а также u
теги):
<root>
<a>Some <b /> text <i>that</i> I <u /> want to keep.</a>
</root>
Кроме того, вот решение с использованием xml.dom.minodom
:
import xml.dom.minidom
data = """<root>
<a>Some <b>bad</b> text <i>that</i> I <u>do <i>not</i></u> want to keep.</a>
</root>"""
dom = xml.dom.minidom.parseString(data)
a = dom.getElementsByTagName('a')[0]
for child in a.childNodes:
if getattr(child, 'tagName', '') in ('u', 'b'):
a.removeChild(child)
print dom.toxml()
печатает:
<?xml version="1.0" ?><root>
<a>Some text <i>that</i> I want to keep.</a>
</root>