Python xml 模块

TOC

  • 什么是xml?
  • xml和json的区别
  • xml现今的应用
  • xml的解析方式
    • xml.etree.ElementTree
    • SAX(xml.parsers.expat)
    • DOM
  • 修改xml
  • 构建xml

什么是xml?

我的理解是,xml存储着数据,是一种数据结构,结构化的存储着数据(已标签为节点的树形结构)

就像字典、列表一样,都是一种特定的数据结构。

只不过字典、列表是python解释器在内存中使用的一种数据结构,而xml是文件这种载体中的一种数据结构。

标签节点(Element):包含名字tag,属性attrib, 值text。

xml和json的区别

都说了xml是一种在文本中的一种数据结构,json是内存中数据序列化方式中的一种,序列化为json后可以写入文本中。json也可以看做一种数据结构,但是json可以表示的数据结构可以有很多如对象,列表,整数,字符串,布尔,所以说json是一种数据交换格式。

xml 现今的应用

由于json数据表达格式的出现,当今不同系统程序间的数据交换大多都是使用json。因为json是足够的轻量级,易读易写易解析,所以json是非常的流行。

而xml则廉颇老矣,应该很多老的系统程序还在延续使用了。因为xml解析和创建都很繁琐,解析访问修改xml的方式也很多,所以导致了xml在新开发的软件中很少使用了。大多传统软件公司还在使用,新兴互联网公司都是用json进行数据文件话,或者数据传递。

xml的解析方式

主要有:

  1. xml.etree.ElementTree 子模块 提供简单有效的解析xml的API以及创建xml
  2. DOM——The Document Object Model 缺点将整个xml加载到内存,占用内存大,解析慢。优点,可以任意遍历树节点。
  3. SAX——The Simple API For Xml 因为是流模式读取解析,所以缺点就是需要自己写代码对每个节点的开始、内容、结尾进行处理。不是任意的遍历,是从头到尾。

1. xml.etree.ElementTree

两个主要类:

1 .1. ElementTree 代表整个xml 树。

  • 怎么实例ElementTree对象

    • ElementTree.parse('xmlfile')
    • 如果xml形式已经是字符串,那么可能就直接将xml字符串实例为Element对象
  • ElementTree level涉及到读xml文件和写xml文件

1 .2. Element 代表一个标签节点,可迭代,可索引访问,可包含子Element对象。有tag,attrib,text属性,分别代表标签名,属性字典,内容(如果内容是一个子Element,那么返回'\n ')

  • 怎么实例Element对象

    • ElementTreeInstance.getroot()
    • ElementTree.fromstring(string) 这就是上面提到的从xml字符串中处理xml内容,这就不必先得到ElementTree对象再得到Element对象。
  • Element是用于处理节点相关的任何操作
  • 需要注意,如果节点的tag有引用命名空间,那么tag明就要带上指定命名空间的值。

<yeather:forecast xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0" code="39" date="23 Apr 2018" day="Mon" high="68" low="51" text="Scattered Showers"/>

xmlns就是命名空间,yweather就是命名空间中的一个变量,会在tag中解析这个变量

  • Element常用方法

    Element.findall(match, namespace=None) 匹配上match的所有直属子element

    Element.find(match, namespace=None) 至匹配第一个直属子element

Element.iter(tag=None) 迭代器中存在等于参数tag的所有节点的子节点,包括子节点的子节点,一直递归下去,所以这个很方便。区别域find和findall是正则匹配并且只在直属子节点。

例如test.xml

<?xml version="1.0"?>
<data>
<country name="Liechtenstein">
<rank>1</rank>
<year>2008</year>
<gdppc>141100</gdppc>
<neighbor name="Austria" direction="E"/>
<neighbor name="Switzerland" direction="W"/>
</country>
<country name="Singapore">
<rank>4</rank>
<year>2011</year>
<gdppc>59900</gdppc>
<neighbor name="Malaysia" direction="N"/>
</country>
<country name="Panama">
<rank>68</rank>
<year>2011</year>
<gdppc>13600</gdppc>
<neighbor name="Costa Rica" direction="W"/>
<neighbor name="Colombia" direction="E"/>
</country>
</data>

解析xml

import xml.etree.ElementTree as ET
eletree = ET.parse('test.xml') # 打开test.xml得到ElementTree对象
root_node = eletree.getroot() # 通过ElementTree对象的getroot得到root标签Element对象
child1 = root_node[0] # Element对象可迭代,支持索引访问协议,返回子节点
child2 = root_node[1]
atrrdict1 = child1.attrib # 获取child1标签的属性,已字典方式返回
child1ofchild1 = child1[0] # 说明如果节点的内容还是节点,那么这个节点是可迭代的,如果节点能获取到text内容,那么这个节点就不能迭代访问了。
print(child1ofchild1.text) # 1 # 还可以遍历节点
for inode in root_node:
print(inode)

2. SAX

使用xml.parsers.expat

使用里面的类ParserCreate()将返回一个xmlparser object,这个对象可以解析xml通过像数据流一样,一个节点一个节点的处理,处理方式是已事件触发式,即遇到节点的事件,调用事件提前做好的处理方法进行处理。

所以这种方式解析xml,需要自己定义事件的处理器,并保存每种事件处理的结果。

主要事件Event有三种:

* StartElement Event

* EndElement Event

* CharactorData Event

要处理哪种事件,就要相应handler赋给ParserCreate

如:

import re
import datetime
from urllib import request
from xml.parsers.expat import ParserCreate
import xml.etree.ElementTree as et with request.urlopen('https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%'
'20%3D%202151330&format=xml') as fp:
wther_cont = fp.read().decode('utf-8') # 已SAX方式解析xml
def parsexml(xml_str):
wth_dict = dict()
wth_dict.setdefault('city', re.search(r'Conditions for\s(?P<city>\w+),', xml_str).group('city')) # 没找到city具体的标签或者属性,替代着用re来处理。
wth_dict.setdefault('forecast', list())
xml_parser = ParserCreate() # a instance of ParserCreate, it is a xml processor. def start_ele(name, attrs): # 定义start_element事件的处理
if name == 'yweather:forecast':
del attrs['xmlns:yweather']
del attrs['code']
del attrs['text']
del attrs['day']
# attrs['date'] = datetime.
wth_dict['forecast'].append(attrs) xml_parser.StartElementHandler = start_ele # 这里只定义了StartElement事件的处理方式
xml_parser.Parse(xml_str)
return wth_dict
print(parsexml(wther_cont))
  • xmlparser.Parse() 与 xmlparser.ParseFile(file) 分别是xml字符串和xml文件作为参数进行解析
  • 因为每种事件的处理,所以最好自己在定义一个类,提供事件的处理方法,和存储事件处理想要从xml中得到的数据。

3. DOM

修改XML

提供修改主要使用xml.etree.ElementTree模块

模块的ElementTree对象提供写入和读取xml,所以修改xml后,通过ElementTree.write(file)方法将修改后的xml写入xml文件中。

其实修改内容就是修改element对象的各种属性的值,如tag,attrib,text。

例如test.xml进行修改

import xml.etree.ElementTree as ET
eletree = ET.parse('./test.xml')
root_ele = eletree.getroot()
root_ele[0].attrib.pop('name')
eletree.write('./test.xml')

结果test.xml变为

<data>
<country> # 没有了name
<rank>1</rank>
<year>2008</year>
<gdppc>141100</gdppc>
<neighbor direction="E" name="Austria" />
<neighbor direction="W" name="Switzerland" />
</country>
<country name="Singapore">
<rank>4</rank>
<year>2011</year>
<gdppc>59900</gdppc>
<neighbor direction="N" name="Malaysia" />
</country>
<country name="Panama">
<rank>68</rank>
<year>2011</year>
<gdppc>13600</gdppc>
<neighbor direction="W" name="Costa Rica" />
<neighbor direction="E" name="Colombia" />
</country>
</data>

还可以删除某节点的子节点,element.remove(subelement)

import xml.etree.ElementTree as ET
eletree = ET.parse('./test.xml')
root_ele = eletree.getroot()
root_ele.remove(root_ele[2])
eletree.write('./test.xml')

test.xml变为

<data>
<country>
<rank>1</rank>
<year>2008</year>
<gdppc>141100</gdppc>
<neighbor direction="E" name="Austria" />
<neighbor direction="W" name="Switzerland" />
</country>
<country name="Singapore">
<rank>4</rank>
<year>2011</year>
<gdppc>59900</gdppc>
<neighbor direction="N" name="Malaysia" />
</country>
</data>

构建XML

  1. 最简单方式,直接拼接字符串
  2. 通过ElementTree对象的方法构建

a = ET.Element('a')

b = ET.SubElement(a, 'b')

c = ET.SubElement(a, 'c')

d = ET.SubElement(c, 'd')

ET.dump(a)

<a><b /><c><d /></c></a>

可以通过Element操作丰富内容

给test.xml的root节点添加一个节点

import xml.etree.ElementTree as ET
eletree = ET.parse('./test.xml')
root_ele = eletree.getroot()
haha = ET.SubElement(root_ele, 'haha')
haha.attrib.setdefault('test','testvalue')
haha.text = 'hellworld'
eletree.write('./test.xml')

结果:

<data>
<country>
<rank>1</rank>
<year>2008</year>
<gdppc>141100</gdppc>
<neighbor direction="E" name="Austria" />
<neighbor direction="W" name="Switzerland" />
</country>
<country name="Singapore">
<rank>4</rank>
<year>2011</year>
<gdppc>59900</gdppc>
<neighbor direction="N" name="Malaysia" />
</country>
<haha test="testvalue">
hellworld
</haha>
</data>

这次算是终于理解了xml的结构和解析。注意xml中的namespace。

Python xml 模块的更多相关文章

  1. Python xml模块

    xml模块 自己创建xml文档 import xml.etree.cElementTree as ET new_xml = ET.Element("personinfolist") ...

  2. 16 python xml模块

    1.基本概念 xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单. 不过,古时候,在json还没诞生的黑暗年代,大家只能选择用xml呀. 至今很多传统公司如金 ...

  3. python解析xml模块封装代码

    在python中解析xml文件的模块用法,以及对模块封装的方法.原文转自:http://www.jbxue.com/article/16586.html 有如下的xml文件:<?xml vers ...

  4. python全栈开发-hashlib模块(数据加密)、suprocess模块、xml模块

    一.hashlib模块 1.什么叫hash:hash是一种算法(3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法 ...

  5. 【python标准库模块五】Xml模块学习

    Xml模块 xml本身是一种格式规范,是一种包含了数据以及数据说明的文本格式规范.在json没有兴起之前各行各业进行数据交换的时候用的就是这个.目前在金融行业也在广泛在运用. 举个简单的例子,xml是 ...

  6. python configparse模块&xml模块

    configparse模块 用于生成和修改常见配置文档,当前模块的名称在 python 3.x 版本中变更为 configparser. [DEFAULT] serveraliveinterval = ...

  7. Learning-Python【20】:Python常用模块(3)—— shelve、pickle、json、xml、configparser

    什么是序列化/反序列化? 序列化就是将内存中的数据结构转换成一种中间格式存储到硬盘或者基于网络传输,反序列化就是硬盘中或者网络中传来的一种数据格式转换成内存中数据结构 为什么要有序列化/反序列化? 1 ...

  8. python(32)——【shelve模块】【xml模块】

    一. shelve模块 json和pickle模块的序列化和反序列化处理,他们有一个不足是在python 3中不能多次dump和load,shelve模块则可以规避这个问题. shelve模块是一个简 ...

  9. Python常用内置模块之xml模块

    xml即可扩展标记语言,它可以用来标记数据.定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言.从结构上,很像HTML超文本标记语言.但他们被设计的目的是不同的,超文本标记语言被设计用来显示 ...

随机推荐

  1. linux操作命令之帮助命令

    一.man命令的帮助: man 命令名 获取指定命令的帮助 例如man ls 查看ls的帮助 man man可以看到man有8个级别的man帮助命令使用场景 1.查看命令的帮助 2.查看可被内核调用的 ...

  2. 微信小程序用户信息解密失败导致的内存泄漏问题。

    微信小程序获取用户解密的Session_key 然后对 encryptedData进行解密 偶尔报错 时间长了之后会报内存溢出: java.lang.OutOfMemoryError: GC over ...

  3. [Swift]LeetCode482. 密钥格式化 | License Key Formatting

    You are given a license key represented as a string S which consists only alphanumeric character and ...

  4. [Swift]LeetCode712. 两个字符串的最小ASCII删除和 | Minimum ASCII Delete Sum for Two Strings

    Given two strings s1, s2, find the lowest ASCII sum of deleted characters to make two strings equal. ...

  5. Java9发布回顾Java 8的十大新特性

    java9已经在北京时间9月22日正式发布,开发者可以在oracle jdk官网上下载到最新的jdk9. 今天,我们先来一起复习一下2014年发布的Java 8的十大新特性.先来喝杯java~~~ 按 ...

  6. Pycharm使用教程(三)(非常详细,非常实用)

    1. 汉化:把resources_zh.jar拷贝到PyCharm的安装目录下的lib目录,重启Pycharm即可. (resources_zh.jar汉化包关注本账号获取:链接: https://p ...

  7. Java接口的实例应用:致敬我的偶像——何塞·穆里尼奥

    文/沉默王二 曹操在<短歌行>中为杜康酒打过一个价值一亿个亿的广告——“何以解忧,唯有杜康”,我替曹操感到惋惜的是他本人并不会收到这笔不菲的代言费.想一想,要是三国时期的明星人物们有这个代 ...

  8. 【干货】基于Owin WebApi 使用OAuth2进行客户端授权服务

    前言:采用Client Credentials方式,即密钥key/password,场景一般是分为客户端限制必须有权限才能使用的模块,这和微信公众号开放平台很类似. 让用户通过客户端去获取自己的tok ...

  9. 采坑:python base64

    需求:  读取文本内容,对字符串进行base64加密 >>> str = 'aaaaaaaaaaaaaaaaaaa\nbbbbbbbbbbbbbbbbbbbbbbbbbbb\nccc ...

  10. Object Pooling(对象池)实现

    在文章开始之前首先要思考的问题是为什么要建立对象池.这和.NET垃圾回收机制有关,正如下面引用所说,内存不是无限的,垃圾回收器最终要回收对象,释放内存.尽管.NET为垃圾回收已经进行了大量优化,例如将 ...