【问题标题】:Remove a root tag from xml/html using tostring() of lxml使用 lxml 的 tostring() 从 xml/html 中删除根标签
【发布时间】:2020-02-15 17:07:33
【问题描述】:

如何制作没有根标签的html文本(通常是<html></html>)?例如,用于 CDATA:

<![CDATA[<div class="foo"></div><p>bar</p>]]>

我的代码:

from lxml import etree

html = etree.Element('root')
etree.SubElement(html, 'div', attrib={'class':'foo'})
etree.SubElement(html, 'p').text='bar'

t = etree.tostring(html)
# '<root><div class="foo"/><p>bar</p></root>'

我不想使用正则表达式来删除根标签。

【问题讨论】:

  • 不过只是打印的问题吗?据我所知,etree.Element 需要有根标签,不能删除。
  • 为什么要删除根元素?如果要创建 CDATA 部分,请使用 etree.CDATA
  • 它可以&lt;![CDATA[&lt;root&gt;&lt;div class="foo"&gt;&lt;/div&gt;&lt;p&gt;bar&lt;/p&gt;&lt;/root&gt;]]&gt;,但是一些网络服务不接受额外的标签。
  • 其他常见的情况,当需要从一些三方html页面中获取只有带有文本格式标签(&lt;b&gt;等)的文本时,没有页面的结构标签,只会垃圾。要保存这样的格式化标签需要使用tostring(),然后是提到的正则表达式。这使得解析 html/xml、正则表达式、文本/xml 向前和向后转换的代码令人困惑......

标签: python lxml cdata


【解决方案1】:

如果您需要没有根元素的所有子元素的文本表示,您可以这样做:

subels = ''.join([etree.tostring(el).decode('ascii') for el in html])

html 是您问题的Element。在这种情况下,subels 是一个字符串:

'<div class="foo"/><p>bar</p>'

这可以进一步改进以使用iter 方法仅获取特定标签。例如:

subels = ''.join([etree.tostring(el).decode('ascii') for el in html.iter('div', 'p'])

将仅返回 'div''p' 标签,因此如果有其他标签,它们将被省略。
您可以使用它来过滤掉不需要的标签,但要小心,因为它可能会破坏文档层次结构:它仍然会返回不需要标签的子标签。

在 cmets 之后编辑

如果根标签有你想要保留的文本属性,只需将其添加回来。

subels = ''.join([html.text] + [etree.tostring(el).decode('ascii') for el in html])

【讨论】:

  • 谢谢。虽然它也删除了根的文本,它与兄弟标签处于同一级别。例如。 ''.join([etree.tostring(el).decode('ascii') for el in etree.fromstring('&lt;root&gt;Some &lt;b&gt;bold&lt;/b&gt; text&lt;/root&gt;'))&lt;b&gt;bold&lt;/b&gt; text.
  • 使用.decode('ascii') 在我的情况下产生了奇怪的输出。 etree.tostring(el, encoding='unicode', pretty_print=True) 运作良好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-19
  • 2016-01-30
  • 2014-08-31
  • 2012-01-23
  • 2011-02-26
  • 1970-01-01
相关资源
最近更新 更多