XML解析库 lxml 教程(二)

简介

本篇文章和上一篇文章主要介绍Element对象的接口


字典接口

在 XML 或 HTML 中每一个标签都有属性, Element类通过字典接口支持属性操作


创建带有属性的Element对象

from lxml import etree

# 带属性的 Element
root = etree.Element("root", name="root", **{"class": "main"})
# 序列化为 XML 标签
root_s = etree.tostring(root).decode()
print(root_s)

打印结果

<root name="root" class="main"/>

注意class是 Python 关键字, 因此无法使用class="main"按名称传参


访问属性

# 访问已有属性
print("name:", root.get("name"))
# 没有相应属性时, 可指定缺省值
print("title:", root.get("title", "element"))

打印结果

name: root
title: element

与字典不同, 无法通过 root["name"] 访问和设置属性值, Element 的魔法方法 __getitem__ 不支持字符串索引


设置属性

# 设置属性
root.set("id", "root-elem")

遍历属性

# 遍历键-值
for k, v in root.items():
    # Python3.7 以上才支持 f-string
    print(f"{k}: {v}")

打印结果

name: root
class: main
id: root-elem

除了 items(), root 与字典一样还支持 keys()values()


获取属性字典

借助于property类, Element对象的attrib属性可视为字典对象

# 将 Element 的 attrib 属性视为字典
print("root.attrib", root.attrib)

# 通过字符串索引修改和访问标签属性
root.attrib["id"] = "root-attrib"
print('root.attrib["id"]:', root.attrib["id"])

# 通过 attrib 修改后, Element 也相应被修改
root_s = etree.tostring(root).decode()
print("root:", root_s)

打印结果

root.attrib: {'name': 'root', 'class': 'main', 'id': 'root-elem'}
root.attrib["id"]: root-attrib
root: <root name="root" class="main" id="root-attrib"/>

对 Element 元素属性的修改会映射到 attrib 属性, 反之亦然


操作属性字典

root.attribroot本身更接近字典

# 更新属性
root.attrib.update({"id": "root-update"})
# 仅遍历值
for v in root.attrib.values():
    print("attribute value:", v)

打印结果

attribute value: root
attribute value: main
attribute value: root-update

添加文本内容

如果将Element对象看做元素节点, 那么其包含的文本就可看做文本节点, 在 lxml 包中Element对象可以添加文本内容


创建包含文本内容的Element对象

from lxml import etree

root = etree.Element("root")
# 设置文本内容
root.text = "Text"
root_s = etree.tostring(root).decode()
print("root:", root_s)

打印结果

root: <root>Text</root>

由于包含文本内容, root 变为双标签


在 XML 文档中, 文本内容只能包含于双标签内, 而 HTML 则不同, 文本内容可位于不同的标签之间, 所以Element对象新增了tail属性, 可在Element 末尾新增文本内容

html = etree.Element("html")
body = etree.SubElement(html, "body")
body.text = "BODY"
span = etree.SubElement(body, "span")
span.text = "SPAN_1"

html_1 = etree.tostring(html, pretty_print=True).decode()
print(html_1)
# 在尾部新增内容
span.tail = "SPAN_2"
html_2 = etree.tostring(html, pretty_print=True).decode()
print(html_2)

打印结果

<html>
  <body>BODY<span>SPAN_1</span></body>
</html>

<html>
  <body>BODY<span>SPAN_1</span>SPAN_2</body>
</html>

在序列化 Element 对象时, 可以忽略末尾文本, 也可以仅输出文本内容

# 忽略末尾文本
html_3 = etree.tostring(html, with_tail=True, pretty_print=True).decode()
print(html_3)
# 仅文本内容
html_4 = etree.tostring(html, method='text').decode()
print(html_4)

打印结果

<html>
  <body>BODY<span>SPAN_1</span>SPAN_2</body>
</html>

BODYSPAN_1SPAN_2
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值