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. IIS中 flv、swf 文件无法播放

    解决方案: 1.服务器安装flash,这是必须的. 2.MIME类型添加两个:名称.swf,值application/x-shockwave-flash:名称.flv,值flv-application ...

  2. [转]Understanding OpenStack Authentication: Keystone PKI

    The latest stable release of OpenStack, codenamed Grizzly, revolutionizes the way user authenticatio ...

  3. [Swift]LeetCode728. 自除数 | Self Dividing Numbers

    A self-dividing number is a number that is divisible by every digit it contains. For example, 128 is ...

  4. (转)浅谈Session与Cookie的区别与联系

    一.Session的概念 Session 是存放在服务器端的,类似于Session结构来存放用户数据,当浏览器 第一次发送请求时,服务器自动生成了一个Session和一个Session ID用来唯一标 ...

  5. Python——day12 nonlcoal关键字、装饰器(开放封闭原则、函数被装饰、最终写法)

    一.nonlocal关键字 1.作用:将L与E(E中的名字需要提前定义)的名字统一 2.应用场景:如果想在被嵌套的函数中修改外部函数变量(名字)的值 def outer(): num=10 print ...

  6. 【Spark篇】---Spark中控制算子

    一.前述 Spark中控制算子也是懒执行的,需要Action算子触发才能执行,主要是为了对数据进行缓存. 控制算子有三种,cache,persist,checkpoint,以上算子都可以将RDD持久化 ...

  7. 对vue源码的初步认识和理解

    根据vue的官网介绍,可以得知vue是一个mvvm框架,且是响应式的.为了更深入了理解其内涵,本人以及理解实现了一个简单的mvvm学习的demo.下面分享给大家,欢迎大家一起讨论. 一.mvvm至少包 ...

  8. Quartz.NET学习笔记(一) 简介

    Quartz.NET是一款开源的任务调度框架,他是由Java中的任务调度框架Quartz移植而来的.官方网站https://www.quartz-scheduler.net/. Quartz.Net的 ...

  9. 纽约工作日志流水账 Day 1

    周六早上8:00从青岛登机,历经17个小时,终于在当地时间周六下午2点半到达目的地纽约.         被媳妇吐槽旁边坐了美女妹子,其实是个美国妹子,旁边人家还有男朋友,全程只和我说了2句话,Exc ...

  10. Linux上安装Zookeeper以及一些注意事项

    最近打算出一个系列,介绍Dubbo的使用. 分布式应用现在已经越来越广泛,Spring Could也是一个不错的一站式解决方案,不过据我了解国内目前貌似使用阿里Dubbo的公司比较多,一方面这个框架也 ...