Удалить все вложенные теги XML

Я пытаюсь удалить все «вложенные теги одного типа». Если для каждого элемента XML вы обнаружите в его поддереве другой подэлемент с таким же именем, удалите его тег (сохраните его содержимое). Другими словами, превратите <a>...<a>...</a>...</a> в <a>.........</a>.

Я создал очень красивый и простой фрагмент кода, используя функции iter и Strip_tags из пакета lxml:

import lxml.etree

root = lxml.etree.parse('book.txt')

for element in root.iter():
    lxml.etree.strip_tags(element, element.tag)

print(lxml.etree.tostring(root).decode())

Я использовал этот входной файл:

<book>
    <b><title>My <b>First</b> Book</title></b>
    <i>Introduction <i><i>To</i></i> LXML</i>
    <name><a>Author: <a>James</a></a></name>
</book>

и я получил этот вывод:

<book>
    <b><title>My First Book</title></b>
    <i>Introduction To LXML</i>
    <name><a>Author: <a>James</a></a></name>
</book>

Как видите, удалены почти все вложенные теги, кроме одного: <a>Author: <a>James</a></a>. Что не так с кодом? Как я могу это исправить?

Просто здравый вопрос: поддерживает ли etree.iter() изменение дерева во время обхода?

forty-two 30.04.2024 17:46

что, если у вас будет элемент, вложенный в уже вложенный элемент? Возможно, потребуется использовать рекурсию.

furas 30.04.2024 18:30

Возможно, сначала используйте print()print(type(...)), print(len(...)) и т. д.), чтобы увидеть, какая часть кода выполняется и что на самом деле у вас есть в переменных. Он называется "print debugging" и помогает увидеть, что на самом деле делает код.

furas 30.04.2024 18:32

когда я запускаю print( element.tag ) в for-цикле, я не показываю name и a. Вероятно, существует аналогичная проблема, например, с удалением элементов из списка при повторении списка.

furas 30.04.2024 18:36
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
4
98
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Небезопасно изменять XML-дерево во время его итерации. Вместо этого переберите список всех элементов.

import lxml.etree

root = lxml.etree.parse('book.txt')

all_elements = list(root.iter())

for element in all_elements:
    lxml.etree.strip_tags(element, element.tag)
    
print(lxml.etree.tostring(root).decode())

Выход:

<book>
    <b><title>My First Book</title></b>
    <i>Introduction To LXML</i>
    <name><a>Author: James</a></name>
</book>

Это так умно и элегантно! Конечно, это может показаться очевидным тем, кто уже знает суть. Я не забуду сохранить «план итерации» в безопасности и в стороне, прежде чем начну вносить изменения. Спасибо.

Jeyekomon 02.05.2024 09:35

См. также stackoverflow.com/q/3346696/407651

mzjn 02.05.2024 10:12

В XSLT это

<xsl:template match = "*[node-name() = ancestor::*/node-name()]">
  <xsl:apply-templates/>
</xsl:template>

Другие вопросы по теме