使用lxml在一个元素后添加另一个元素

23 投票
3 回答
37336 浏览
提问于 2025-04-17 02:37

我有以下的HTML代码

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

为了修复一些CSS的问题,我想在content_nav这个div后面加一个div标签,内容是<div style="clear:both"></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 id="content_nav">
    something goes here
    <div style="clear:both"></div>
</div>

有没有办法在content_nav这个div的中间加一个div,然后在contents里面加一些p标签呢?

谢谢

3 个回答

2

我觉得一个通用的函数来解决“在另一个元素后插入一个元素”这个问题可能会很有用,即使它只是对已有答案的重新表述:

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

这个函数可以让你在一个已有的元素后面,轻松地插入一个新元素,只需要

insert_after(element, new_element)
17

使用 addpreviousaddnext 来添加兄弟节点。

在 lxml.etree 的 _Element 中,有两个方法:addpreviousaddnext,它们正好可以满足你的需求。

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>
38

与其把内容添加到 contentnav,不如先找到它的父元素 contentdiv,然后在一个特定的位置插入新的 div。要找到这个位置,可以使用 contentdiv.index(contentnav),这个方法会告诉你 contentnavcontentdiv 中的位置。再加上1,就能得到你想要的位置。

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>

撰写回答