当仅打印部分文档时,lxml的tostring()
函数似乎很破碎。证人:
from lxml.html import fragment_fromstring, tostring
frag = fragment_fromstring('<p>This stuff is <em>really</em> great!')
em = frag.cssselect('em').pop(0)
print tostring(em)
我希望<em>really</em>
,而是打印<em>really</em> great!
错误。最棒的 !' 不是所选em
的一部分。它不仅是错误的,它还是一个药丸,至少对于处理文档结构化的XML而言,这种结尾的文本很常见。
据我了解,lxml存储元素.tail
属性中当前元素之后的所有自由文本。扫描tostring()
的代码会将我带到ElementTree.py的_write()
函数,该函数显然始终打印尾部。这是整个树的正确行为,但在渲染子树时不是最后一个元素,但它没有区别。
为了获得所选XML的正确无尾渲染,我尝试从头开始编写toxml()
函数以在其中使用。它基本上有效,但在处理注释,处理指令,命名空间,编码,yadda yadda时有许多特殊情况。所以我改变了方向,现在只需背负tostring()
,对其输出进行后处理,以删除有问题的.tail
文本:
def toxml(e):
""" Replacement for lxml's tostring() method that doesn't add spurious
tail text. """
from lxml.etree import tostring
xml = tostring(e)
if e.tail:
xml = xml[:-len(e.tail)]
return xml
一系列基本测试表明这很有效。
批评和/或建议?
答案 0 :(得分:12)
xml = lxml.etree.tostring(e, with_tail=False)
怎么样?
from lxml.html import fragment_fromstring
from lxml.etree import tostring
frag = fragment_fromstring('<p>This stuff is <em>really</em> great!')
em = frag.cssselect('em').pop(0)
print tostring(em, with_tail=False)
看起来在v2.0中添加了with_tail
;你有旧版本吗?