【问题标题】:Delete child nodes after a certain child node删除某个子节点后的子节点
【发布时间】:2018-10-22 14:32:08
【问题描述】:

我想删除一个元素中位于<hr/> 元素(包括<hr/>)之下的所有节点(包括文本)。

例如,这个:

<td class="one">
    Some text
    <a href="page1.html"/>
    <br/>
    Some more text
    <br/>
    <a href="page2.html"/>
    <hr/>
    Bottom text
    <br/>
    <a href="page3.html"/>
</td>

应该变成:

<td class="one">
    Some text
    <a href="page1.html"/>
    <br/>
    Some more text
    <br/>
    <a href="page2.html"/>
</td>

我有这个 XPath 可以找到&lt;hr/&gt; 下的所有元素:

./node()[ preceding-sibling::hr[not(following-sibling::hr)] ]

但我不知道如何删除这些元素。 我试着这样做:

xp = './node()[ preceding-sibling::hr[not(following-sibling::hr)] ]'
els = self.xpath(xp, td_el)
for el in els:
    el.getparent().remove(el)

但它不适用于文本节点。

最好的方法是什么? 谢谢。

【问题讨论】:

    标签: python xpath lxml


    【解决方案1】:

    尝试使用以下代码删除节点:

    from lxml import etree, html
    
    source = """<td class="one">
        Some text
        <a href="page1.html"/>
        <br/>
        Some more text
        <br/>
        <a href="page2.html"/>
        <hr/>
        Bottom text
        <br/>
        <a href="page3.html"/>
    </td>"""
    html = html.fromstring(source)
    parent = html.xpath('//td')[0]
    redundant = html.xpath('//hr/preceding-sibling::*[1]/following-sibling::*')
    
    for node in redundant:
        parent.remove(node)
    
    print(etree.tostring(parent))
    

    输出

    <td class="one">
        Some text
        <a href="page1.html"/>
        <br/>
        Some more text
        <br/>
        <a href="page2.html"/>
    </td>
    

    【讨论】:

    • 它有效,谢谢!但是我不清楚为什么这里的节点会删除文本(当然,这是我需要的)。 redundant 列表不包含文本节点。
    • @user10540755 这是由于lxml 的细节:lxml 不将文本节点识别为Element 对象,而是作为简单的字符串。因此,当您执行html.xpath('//*') 时,您只会获得Element 对象的列表。如果你这样做html.xpath('//text()') - 你会得到文本节点列表(字符串)
    猜你喜欢
    • 1970-01-01
    • 2013-11-09
    • 2011-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-04
    相关资源
    最近更新 更多