python etree模块所有函数详解_09.XML处理之etree模块

本主题主要说明python的xml处理标准模块xml.etree的使用。xml.etree模块包含4个子模块,其中cElementTree是ElementTree的别名,已经不推荐使用。本主题主要包含内容:

1. ElementInclude模块使用

2. ElementPath模块使用

3. ElementTree模块使用

一、etree模块帮助

import xml.etree

help(xml.etree)

Help on package xml.etree in xml:

NAME

xml.etree

DESCRIPTION

# $Id: __init__.py 3375 2008-02-13 08:05:08Z fredrik $

# elementtree package

PACKAGE CONTENTS

ElementInclude

ElementPath

ElementTree

cElementTree

FILE

/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/xml/etree/__init__.py

提供四个模块:

|- ElementInclude

|- ElementPath

|- ElementTree

|- cElementTree

二、ElementInclude模块

ElementInclude模块主要提供xml中xinclude展开使用。

提供了几个异常类:

FatalIncludeError

|-builtins.SyntaxError

|-builtins.Exception

|-builtins.BaseException

|-builtins.object

提供了两个函数:

FUNCTIONS

|-default_loader(href, parse, encoding=None)

|-include(elem, loader=None)

提供了三个常量:

DATA

|-XINCLUDE = '{http://www.w3.org/2001/XInclude}'

|-XINCLUDE_FALLBACK = '{http://www.w3.org/2001/XInclude}fallback'

|-XINCLUDE_INCLUDE = '{http://www.w3.org/2001/XInclude}include'

2.1. 使用xinclude语法的xml文件

1. webpages.xml文件

2. footer.xml文件

Mage Education, 2019

2.2. 使用default_loader加载xml文件

函数default_loader加载任何文本文件,不过按照xml加载就返回Element对象,非xml就返回str字符串。

函数原型如下:

default_loader(href, parse, encoding=None)

|- href:用来指定加载的xml文件

|- parse:指定解析的类型:xml与非xml,xml就返回xml.etree.ElementTree.Element类型,否则字符串。

|- encoding:对非xml有用,用来指定编码格式,一般就是utf-8了。

import xml.etree.ElementInclude

# 非xml解析,直接返回字符串

result = xml.etree.ElementInclude.default_loader(

href='codes/webpages.xml',

parse='text',

encoding='utf-8')

print(':', type(result))

print(result)

print('------------------')

# 作为xml解析返回xml.etree.ElementTree.Element对象。

result = xml.etree.ElementInclude.default_loader(

href='codes/webpages.xml',

parse='xml',

encoding='utf-8')

print(':', type(result))

print(result)

:

------------------

:

2.3. 使用include函数扩展xinclude

函数include用来展开xml中的xinclude指令。

函数原型如下:

include(elem, loader=None)

|- elem:要扩展xinclude的元素。

|- loader:只加载扩展xml文件的加载器,默认是default_loader函数加载器。

注意:

经过include函数处理的元素,如果包含include指令,则会展开成xml的文件。 可以仔细观察西面例子的输出。

import xml.etree.ElementInclude

# 由于版本变化,默认的常量值,可以根据已有的文档修改。

xml.etree.ElementInclude.XINCLUDE_INCLUDE='{http://www.w3.org/2003/XInclude}include'

# 作为xml解析返回xml.etree.ElementTree.Element对象。

result = xml.etree.ElementInclude.default_loader(

href='codes/webpages.xml',

parse='xml',

encoding='utf-8')

print('xinclude扩展前输出')

for ele in result:

print(type(ele),ele)

xml.etree.ElementInclude.include(result, loader=None)

print('xinclude扩展后输出')

for ele in result:

print(type(ele),ele)

xinclude扩展前输出

xinclude扩展后输出

三、ElementPath模块

提供XPath的支持。

支持XPath的函数如下:

FUNCTIONS

|- find(elem, path, namespaces=None)

|- findall(elem, path, namespaces=None)

|- findtext(elem, path, default=None, namespaces=None)

|- get_parent_map(context)

|- iterfind(elem, path, namespaces=None)

|- prepare_child(next, token)

|- prepare_descendant(next, token)

|- prepare_parent(next, token)

|- prepare_predicate(next, token)

|- prepare_self(next, token)

|- prepare_star(next, token)

|- xpath_tokenizer(pattern, namespaces=None)

其中提供的常量数据有:

|- ops = {'': , '': , '.'...

|- xpath_tokenizer_re = re.compile('('[^']'|\"[^\"]*\"|::|//?|\.....

注意:

其中prepare_XXX函数就是ops的操作列表,操作会被iterfind使用,被用来解析path的每个部分,一般不直接使用。下面也不介绍。

实际ElementTree中的path操作方式也是使用这里的find系列函数。

下面是xpath支持的语法:

xpath语法

说明

tag

选择所有tag子元素

*

选择一级子元素,比如*/egg选在孙子元素egg

.

表示当前元素

//

所有子元素,比如.//egg选在任何级别节点上的egg元素。

..

上级父元素

[@attrib]

具有属性attrib的元素

[@attrib='value']

属性值等于value的元素

[tag]

所有具有tag子元素的元素

[tag='text']

选择子节点是tag,同时内容为text的元素

[position]

选在给定位置的元素(1表示第一个), last()表示最后一个,last()-1从最后开始计数.

3.1. findall函数

findall函数返回一个列表,原型实现如下:

def findall(elem, path, namespaces=None):

return list(iterfind(elem, path, namespaces))

findall本质是调用iterfind函数实现。

参数说明:

elem:被搜索的元素。

path:查找路径。

namespaces=None:指定path的命名空间。

import xml.etree.ElementPath

import xml.etree.ElementInclude

print(xml.etree.ElementPath.ops)

print(xml.etree.ElementPath.xpath_tokenizer_re)

root = xml.etree.ElementInclude.default_loader('codes/books.xml', 'xml')

eles = xml.etree.ElementPath.findall(root, 'book')

print('findall结果:----------')

print(eles)

{'': , '*': , '.': , '..': , '//': , '[': }

re.compile('(\'[^\']*\'|\\"[^\\"]*\\"|::|//?|\\.\\.|\\(\\)|[/.*:\\[\\]\\(\\)@=])|((?:\\{[^}]+\\})?[^/\\[\\]\\(\\)@=\\s]+)|\\s+')

findall结果:----------

[, , ]

3.2. find函数

find函数返回查找的第一个元素,函数原型实现如下:

def find(elem, path, namespaces=None):

return next(iterfind(elem, path, namespaces), None)

从find的实现代码中可以看出,实际find每次返回都是iterfind返回的迭代器中的下一个元素,因为iterfind每次返回都是全新的查找的结果,所以find每次返回都是查找列表中的第一个。

import xml.etree.ElementPath

import xml.etree.ElementInclude

root = xml.etree.ElementInclude.default_loader('codes/books.xml', 'xml')

ele = xml.etree.ElementPath.find(root, 'book')

if ele:

print(ele.attrib)

{'category': 'Python'}

3.3. findtext函数

findtext是查找满足path条件的text内容,函数原型如下:

def findtext(elem, path, default=None, namespaces=None):

try:

elem = next(iterfind(elem, path, namespaces))

return elem.text or ""

except StopIteration:

return default

注意:返回的不是查找的元素,而是元素的text文本。

参数说明:

default:就是找到的元素没有文本内容的时候,使用该值替代。

import xml.etree.ElementPath

import xml.etree.ElementInclude

root = xml.etree.ElementInclude.default_loader('codes/note.xml', 'xml')

ele = xml.etree.ElementPath.findtext(root, 'to', '缺省值')

print(ele)

Tove

3.4. iterfind函数

iterfind返回一个迭代器类型,实际本质是一个生成器(class 'generator'),该函数的原型实现如下:

def iterfind(elem, path, namespaces=None):

import xml.etree.ElementPath

import xml.etree.ElementInclude

root = xml.etree.ElementInclude.default_loader('codes/books.xml', 'xml')

eles = xml.etree.ElementPath.iterfind(root, 'book')

print(eles)

print(type(eles))

for e in eles:

print(e)

.select at 0x105a487d8>

四、ElementTree模块

ElementTree模块提供xml的dom解析实现,该模块的类包含:

builtins.SyntaxError(builtins.Exception)

ParseError

builtins.object

Element:xml的基本单元:元素

ElementTree:xml元素构成的树状数据结构

QName:Quality Name:根元素

TreeBuilder:xml树构建器

XMLParser:xml解析器

XMLPullParser:xml非阻塞解析器

同时提供一组快捷函数:

Comment(text=None)

PI = ProcessingInstruction(target, text=None)

ProcessingInstruction(target, text=None)

SubElement(...)

XML(text, parser=None)

XMLID(text, parser=None)

dump(elem)

fromstring = XML(text, parser=None)

fromstringlist(sequence, parser=None)

iselement(element)

iterparse(source, events=None, parser=None)

parse(source, parser=None)

register_namespace(prefix, uri)

tostring(element, encoding=None, method=None, *, short_empty_elements=True)

tostringlist(element, encoding=None, method=None, *, short_empty_elements=True)

4.1. TreeBuilder与XMLParser阻塞解析

TreeBuilder负责构建Element对象树,XMLParser负责解析xml内容。

TreeBuilder提供基本的树的构建功能,我们只要返回root Element元素即可得到Element树。

# coding = utf-8

from xml.etree.ElementTree import TreeBuilder

from xml.etree.ElementTree import XMLParser

class MyBuilder(TreeBuilder):

is_root = True

root_element = None

def start(self, tag, attrs):

elem = super().start(tag, attrs)

if self.is_root:

self.root_element = elem

self.is_root = False

return elem

builder = MyBuilder()

parser = XMLParser(target=builder)

fd = open('codes/books.xml', 'r')

xml_data = fd.read()

parser.feed(xml_data)

root = builder.root_element

for item in root.getchildren():

print(item.tag, ':', item.attrib)

for it in item.getchildren():

print('\t|-', it, ':', it.tag,':', it.text)

book : {'category': 'Python'}

|- : title : 网络爬虫开发

|- : author : 蜘蛛精

|- : year : 2018

|- : price : 66.50

|- : publisher : 清华大学出版社

book : {'category': '系统运维'}

|- : title : K8S运维指南r

|- : author : 马哥教育

|- : year : 2018

|- : price : 99.00

|- : publisher : 机械版社

book : {'category': '区块链'}

|- : title : 以太坊智能合约开发

|- : author : 钱多多

|- : year : 2019

|- : price : 88.95

|- : publisher : 邮电出版社

4.2. XMLPullParser 非阻塞解析

XMLPullParser与XMLParser的区别是非阻塞,阻塞的特点在指定回调事件,非阻塞的特点是产生事件列表。

XMLPullParser的read_events(self)返回的是一个数据生成器,也是迭代器。

其中第一个节点就是root节点,可以直接遍历。

# coding = utf-8

from xml.etree.ElementTree import XMLPullParser

events = ("start", "end", "start-ns", "end-ns")

parser = XMLPullParser(events=events)

fd = open('codes/books.xml', 'r')

xml_data = fd.read()

parser.feed(xml_data)

# 转换成列表操作

re_events = list(parser.read_events())

# 构造xml的root

root_element = re_events[0][1]

# 从根节点偏离element树

def list_tree(element, depth):

print('\t' * depth, element.tag, ":", element.text if element.text.strip() != '' else '')

children_elements = element.getchildren()

if children_elements:

for e_ in children_elements:

list_tree(e_, depth+1)

list_tree(root_element, 0)

books :

book :

title : 网络爬虫开发

author : 蜘蛛精

year : 2018

price : 66.50

publisher : 清华大学出版社

book :

title : K8S运维指南r

author : 马哥教育

year : 2018

price : 99.00

publisher : 机械版社

book :

title : 以太坊智能合约开发

author : 钱多多

year : 2019

price : 88.95

publisher : 邮电出版社

4.3. Element对象与ElementTree对象

ElementTree实际是Element的封装,从上面的XMLParser与XMLPullParser可以看出,已经实现基本的Element树结构。

ElementTree与XMLParser、XMLPullParser返回的Element都是Element树结构。但ElementTree提供更加快捷的XMLParser、XMLPullParser的解析功能与xml加载功能,同时提供xml保存功能。

Element对象就是每个标签的封装,提供如下基本数据封装。

| -attrib

|  类型是字典,用来封装元素的所有属性。

|

| -tag

|  类型字符串,用来封装元素的标签名。

|

| -tail

|   类型字符串,标签结束后的文本,也可以是None。

|

| -text

| 类型字符串,开始标签后的文本,也可以是None。

构造器:

| __init__(self, /, *args, **kwargs)

同时提供了一组对封装数据的操作函数:

|

| -makeelement(self, tag, attrib, /)

|

| -append(self, subelement, /)

|

| -insert(self, index, subelement, /)

|

| -remove(self, subelement, /)

|

| -set(self, key, value, /)

|

| -clear(self, /)

|

| -extend(self, elements, /)

|

| -find(self, /, path, namespaces=None)

|

| -findall(self, /, path, namespaces=None)

|

| -findtext(self, /, path, default=None, namespaces=None)

|

| -get(self, /, key, default=None)

|

| -getchildren(self, /)

|

| -getiterator(...)

|  iter($self, /, tag=None)

|  --

|

| -items(self, /)

|

| -iter(self, /, tag=None)

|

| -iterfind(self, /, path, namespaces=None)

|

| -itertext(self, /)

|

| -keys(self, /)

| - __init__(self, element=None, file=None)

| - find(self, path, namespaces=None)

| - findall(self, path, namespaces=None)

| - findtext(self, path, default=None, namespaces=None)

| - getiterator(self, tag=None)

| - getroot(self)

| - iter(self, tag=None)

| - iterfind(self, path, namespaces=None)

| - parse(self, source, parser=None)

| - write(self, file_or_filename, encoding=None, xml_declaration=None, default_namespace=None, method=None, *, short_empty_elements=True)

| - write_c14n(self, file)

注意:

c14n说明:W3C推出了C14n标准用于XML数据的规范化。

目前还没有c14n真正的实现。

# coding = utf-8

from xml.etree.ElementTree import ElementTree

from xml.etree.ElementTree import Element

tree = ElementTree()

tree.parse('codes/books.xml')

root_element = tree.getroot()

# 从根节点偏离element树

def list_tree(element, depth):

print('\t' * depth, element.tag, ":", element.text if element.text.strip() != '' else '')

children_elements = element.getchildren()

if children_elements:

for e_ in children_elements:

list_tree(e_, depth+1)

list_tree(root_element, 0)

books :

book :

title : 网络爬虫开发

author : 蜘蛛精

year : 2018

price : 66.50

publisher : 清华大学出版社

book :

title : K8S运维指南r

author : 马哥教育

year : 2018

price : 99.00

publisher : 机械版社

book :

title : 以太坊智能合约开发

author : 钱多多

year : 2019

price : 88.95

publisher : 邮电出版社

ElementTree还可以通过构造器封装root元素,提供更加方便的操作。

五、cElementTree模块

cElementTree模块是xml.etree.ElementTree模块的别名,目前已经不推荐使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值