(翻译)Lxml教程之文本处理

前言

Lxml是处理XML和Html的强大工具,但对于文本处理的方式和常见的DOM不同,特翻译相关文档,并增加部分注释。

1. Elements中的文本

Elements可以包含文本(text)。

>>> root = etree.Element("root")
>>> root.text = "TEXT"

>>> print(root.text)
TEXT

>>> etree.tostring(root)
b'<root>TEXT</root>'

在许多XML文档中(数据密集型文档),这是唯一可以找到文本的地方。它由树层次结构最底层的叶子标签(leaf tag)封装。

但是,如果 XML 用于“标记文本文档”(如 (X)HTML),则文本也可以出现在不同元素之间,恰好在树的中间。

译注:中间是和叶子节点对比的说法,表示没有被最底层的节点包围。

<html><body>Hello<br/>World</body></html>

此处,<br/>标记被文本包围。这通常称为文档样式(document-style)或混合内容 XML(mixed-content XML)。Elements通过其tail属性支持这一点。它包含直接跟随该元素的文本,直至 XML 树中的下一个元素:

>>> html = etree.Element("html")
>>> body = etree.SubElement(html, "body")
>>> body.text = "TEXT"

>>> etree.tostring(html)
b'<html><body>TEXT</body></html>'

>>> br = etree.SubElement(body, "br")
>>> etree.tostring(html)
b'<html><body>TEXT<br/></body></html>'

>>> br.tail = "TAIL"
>>> etree.tostring(html)
b'<html><body>TEXT<br/>TAIL</body></html>'

.text 和 .tail 这两个属性足以表示 XML 文档中的任何文本内容。这样,除了 Element 类之外,ElementTree API 不需要任何特殊的文本节点,这些节点往往会经常造成阻碍(正如您可能从经典的 DOM API 中知道的那样)。

译注:下面介绍了tostring()方法提供的便利功能。

但是,在某些情况下,尾部(tail)文本也会妨碍您。例如,当您从树的中间(译注:树的中间节点,也就是序列化树的一个子树)序列化 Element 时,您并不总是希望其尾部文本出现在结果中(尽管您仍然需要其孩子节点的尾部文本)。为此,tostring()函数接受关键字参数with_tail:

>>> etree.tostring(br)
b'<br/>TAIL'
>>> etree.tostring(br, with_tail=False) # lxml.etree only!
b'<br/>'

如果只想读取文本,即不带任何中间标记,则必须以正确的顺序递归连接所有文本和尾部属性。同样,tostring() 函数可以帮上忙,这次使用 method 关键字:

>>> etree.tostring(html, method="text")
b'TEXTTAIL'

2. 使用Xpath来查找文本

提取树的文本内容的另一种方法是 XPath,它还允许您将单独的文本块(text chunks)提取到列表中:

>>> print(html.xpath("string()")) # lxml.etree only!
TEXTTAIL
>>> print(html.xpath("//text()")) # lxml.etree only!
['TEXT', 'TAIL']

如果要频繁地使用它,可以将其包装在函数中:

>>> build_text_list = etree.XPath("//text()") # lxml.etree only!
>>> print(build_text_list(html))
['TEXT', 'TAIL']

请注意,XPath 返回的字符串结果是一个特殊的"智能"对象,它知道其来源(origins)。你可以通过它的getparent方法询问它来自哪里,就像使用Elements对象一样:

>>> texts = build_text_list(html)
>>> print(texts[0])
TEXT
>>> parent = texts[0].getparent()
>>> print(parent.tag)
body

>>> print(texts[1])
TAIL
>>> print(texts[1].getparent().tag)
br

您还可以找出它是正常的文本内容还是尾部文本:

>>> print(texts[0].is_text)
True
>>> print(texts[1].is_text)
False
>>> print(texts[1].is_tail)
True

虽然这适用于 text()函数(译注:这个text()函数,表示xpath表达式最后的text(),例如/root/text())的结果,但 lxml 不会告诉您由 XPath 函数 string()或 concat() 构造的字符串值的来源:

>>> stringify = etree.XPath("string()")
>>> print(stringify(html))
TEXTTAIL
>>> print(stringify(html).getparent())
None
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值