Подтвердить что ты не робот

Элемент добавления python lxml после другого элемента

У меня есть следующая разметка HTML

<div id="contents">
    <div id="content_nav">
        something goes here
    </div>
    <p>
        some contents
    </p>   
</div>

Чтобы исправить некоторую проблему с CSS, я хочу добавить тег div <div style="clear:both"></div> после content_nav div, подобного этому

<div id="contents">
    <div id="content_nav">
        something goes here
    </div>

    <div style="clear:both"></div>

    <p>
        some contents
    </p>   
</div>

Я делаю так:

import lxml.etree

tree = lxml.etree.fromString(inputString, parser=lxml.etree.HTMLParser())

contentnav = tree.find(".//div[@id='content_nav']")
contentnav.append(lxml.etree.XML("<div style='clear: both'></div>"))

Но это не добавляет новый div сразу после content_nav div, но внутри.

<div id="content_nav">
    something goes here
    <div style="clear:both"></div>
</div>

Есть ли способ добавить div в середине content_nav div и некоторого p как внутри contents?

Спасибо

4b9b3361

Ответ 1

Вместо добавления к contentnav перейдите к родительскому (contentdiv) и insert новому div к определенному индексу. Чтобы найти этот индекс, используйте contentdiv.index(contentnav), который дает индекс contentnav внутри contentdiv. Добавление одного к которому дает желаемый индекс.

import lxml.etree as ET

content='''\
<div id="contents">
    <div id="content_nav">
        something goes here
    </div>
    <p>
        some contents
    </p>   
</div>
'''
tree = ET.fromstring(content, parser=ET.HTMLParser())
contentnav = tree.find(".//div[@id='content_nav']")
contentdiv = contentnav.getparent()
contentdiv.insert(contentdiv.index(contentnav)+1,
                  ET.XML("<div style='clear: both'></div>"))
print(ET.tostring(tree))

дает

<html><body><div id="contents">
    <div id="content_nav">
        something goes here
    </div>
    <div style="clear: both"/><p>
        some contents
    </p>   
</div></body></html>

Ответ 2

Я считаю, что универсальная функция, обращаясь к вопросу "вставить элемент за другим элементом", может быть полезна, даже если это просто переформулировка принятого ответа:

def insert_after(element, new_element):
    parent = element.getparent()
    parent.insert(parent.index(element)+1, new_element)

который позволяет вставить new_element после существующего element только с

insert_after(element, new_element)

Ответ 3

Используйте addprevious и addnext для добавления и добавления дочерних элементов.

Элемент etree имеет два метода: addprevious и addnext для выполнения именно того, что вы хотите.

import lxml.etree as ET

content='''\
<div id="contents">
    <div id="content_nav">
        something goes here
    </div>
    <p>
        some contents
    </p>   
</div>
'''
tree = ET.fromstring(content, parser=ET.HTMLParser())
contentnav = tree.find(".//div[@id='content_nav']")
contentnav.addnext(ET.XML("<div style='clear: both'></div>"))
print(ET.tostring(tree))

Вывод:

<html><body><div id="contents">
    <div id="content_nav">
        something goes here
    </div><div style="clear: both"/>
    <p>
        some contents
    </p>   
</div>
</body></html>