目录
⭐昨天真忙到太晚了,来不及发布文章,对不住自己。以后会尽可能按时更新文章...🌈
活动地址:CSDN21天学习挑战赛
XML(Extensible Markup language):可扩展标记语言。xml 是互联网数据传输得重要工具,它可以跨越互联网任何的平台,不受编程语言的限制,可以说它是一个拥有互联网最高级别通行证的数据携带者。xml 是当处理结构化文档信息中相当给力的技术,xml 有助于在服务器之间穿梭结构化数据,这使得开发人员更加得心应手地控制数据的存储和传输。
xml 用于标记电子文件,使具有结构性的标记语言可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。 xml 是具有通用标记语言(SGML)的子集,非常适合Web传输。xml 提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据。
特点:
- xml 与编程语言的开发平台无关。
- 可以实现不用系统之间的数据交互。
作用:
- 配置应用程序和网站。
- 数据交互。
- Ajax 基石。
与 HTML 类似,XML 是另一种将数据存储在标记之间的标记语言。它是人类可读可扩展的,也就是说,我们可以自由地定义自己的标记。XML 中属性、元素和标记与 HTML 中的类似。XML 文件可以有声明,也可以没有声明,但是,如果它有一个声明,那么它必须是 XML 文件的第一行。如:
这个声明语句有三部分:版本、编码和独立性。版本说明正在使用的 XML 标准的版本;Encoding 表示在此文件中使用的字符编码类型;Standalone 告诉解析器是否要外部信息来解释 XML 文件的内容。
XML 文件可以表示为:XML树。这个 XML 树从根元素(父元素)开始。这个根元素进一步分支到子元素。XML 文件的每个元素都是 XML 树中的一个节点。那些没有节点的元素是叶节点。
XML 文件格式内容包括:声明、根元素、子元素、属性、命名空间、限定名。
ElementTree 模块提供了一个轻量级、Pythonic 的API,同时还有一个高效的C语言实现,即 xml.etree.cElementTree。与 DOM 相比,ET 的速度更快,API 使用更直接、方便。与 SAX 相比,ET.iterparse 函数同样提供了按需解析的功能,不会一次性在内存中读入整个文档。ET 的性能与 SAX 模块大致相仿,但是它的 API 更加高层次,用户使用器来更加便捷。
类方法 | 说明 |
---|---|
Element.iter(tag=None) | 遍历该 Element 所有后代,也可以指定 tag 进行遍历寻找 |
Element.iterfind(path, namespaces=None) | 根据 tag 或 path 查找所有的后代 |
Element.itertext() | 遍历所有后代并返回 text 值 |
Element.findall(path) | 查找当前元素下 rag 或 path 能够匹配的直系节点 |
Element.findtext(path, defult=Nonr, namespaces=None) | 寻找第一个匹配子元素,返回其 text 值。匹配对象可以为 tag 或 path |
Element.text() | 获取当前元素的 text 值 |
Element.get(key, defult=None) | 获取元素指定 key 对应的属性值,如果没有该属性,则返回 default 值 |
Element.keys() | 返回元素属性名称列表 |
Element.items() | 返回(name, value)列表 |
Element.getchildren() | 获取所有子元素 |
Element.getiterator(tag=None) | Python3.2后使用,Element.iter(tag=None) |
Element.getiterator(self, tag=None) |
方法名 | 说明 |
---|---|
Element.tag | 节点名(tag)(str) |
Element.attrib | 属性(attribes)(dict) |
Element.text | 文本(text)(str) |
Element.tail | 附加文本(tail)(str) |
Element[:] | 子节点列表(list) |
在程序相同目录下创建 test.xml 文件,里面包括:
- <collection shelf="New Arrivals">
- <class className="1班">
- <code>2022001code>
- <number>10number>
- <teacher>小白teacher>
- class>
- <class className="2班">
- <code>2022002code>
- <number>20number>
- <teacher>小红teacher>
- class>
- <class className="3班">
- <code>2022003code>
- <number>30number>
- <teacher>小黑teacher>
- class>
- collection>
用法举例:
- import xml.etree.ElementTree as ET
-
- #1.加载test.xml文档,并进行解析
- tree = ET.ElementTree(file='test.xml')
- #2.获取根元素
- root =tree.getroot()
- print(root) #输出:
- #3.根元素root是一个Element对象,打印其元素
- print(root.tag) #输出:collection
- print(root.attrib) #输出:{'shelf': 'New Arrivals'}
- #4.遍历根元素的直接子元素
- for child_of_root in root:
- print(child_of_root.tag, child_of_root.attrib)
- #输出:class {'className': '1班'}
- # class {'className': '2班'}
- # class {'className': '3班'}
- #5.通过索引值访问特定的子元素
- print(root[0].tag,root[0].attrib) #输出:class {'className': '1班'}
分析:从上面的示例代码中,可以明显地发现,我们能够通过简单的遍历方法获取树中的所用元素。但是,由于这是十分常见的工作,ET 提供了一些简便的实现方法。
Element 对象有一个 iter 方法,可以对某个元素对象之下所有的元素进行深度优先遍历(DFS)。ElementTree 对象同样也有这个方法。下面是查找 XML 文档中所有元素的最简单方法(这点方法和字典遍历类似):
- import xml.etree.ElementTree as ET
-
- #1.加载test.xml文档,并进行解析
- tree = ET.ElementTree(file='test.xml')
-
- for elem in tree.iter():
- print(elem.tag, elem.attrib)
- #输出:
- # collection {'shelf': 'New Arrivals'}
- # class {'className': '1班'}
- # code {}
- # number {}
- # teacher {}
- # class {'className': '2班'}
- # code {}
- # number {}
- # teacher {}
- # class {'className': '3班'}
- # code {}
- # number {}
- # teacher {}
对树进行遍历时,iter 方法也可以接收 tag 名称,然后遍历所有具备所提供 tag 的元素;支持通过 XPath 查找元素;也可以查找所有具备某个 name 属性的 className元素:
- import xml.etree.ElementTree as ET
-
- #加载test.xml文档,并进行解析
- tree = ET.ElementTree(file='test.xml')
-
- #遍历所有节点名tag=teacher的元素
- for elem in tree.iter(tag='teacher'):
- print(elem.tag, elem.text)
- # 输出:teacher 小白
- # teacher 小红
- # teacher 小黑
-
- #通过XPath查找class下面teacher元素
- for elem in tree.iterfind('class/teacher'):
- print(elem.tag,elem.text)
- # 输出:teacher 小白
- # teacher 小红
- # teacher 小黑
-
- #查找所有具备class下className="1班"的元素
- for elem in tree.iterfind('class[@className="1班"]'):
- print(elem.tag,elem.attrib)
- # 输出:class {'className': '1班'}
遍历 xml 文件中所有元素的完整解析代码如下:
- import xml.etree.ElementTree as ET
-
- #加载test.xml文档,并进行解析
- tree = ET.ElementTree(file='test.xml')
- print(type(tree)) #输出:
- #获取根元素
- root = tree.getroot()
- print(type(root)) #输出:
- print(root.tag) #输出:collection
- #遍历剩余所有元素
- for index,child in enumerate(root):
- print("第%s个%s元素, 属性:%s"%(index, child.tag, child.attrib))
- for i,child_child in enumerate(child):
- print("标签:%s,内容:%s"%(child_child.tag,child_child.text))
- # 输出:
- # 第0个class元素, 属性:{'className': '1班'}
- # 标签:code,内容:2022001
- # 标签:number,内容:10
- # 标签:teacher,内容:小白
- # 第1个class元素, 属性:{'className': '2班'}
- # 标签:code,内容:2022002
- # 标签:number,内容:20
- # 标签:teacher,内容:小红
- # 第2个class元素, 属性:{'className': '3班'}
- # 标签:code,内容:2022003
- # 标签:number,内容:30
- # 标签:teacher,内容:小黑
DOM(Document Object Model)将 XML 文档作为一棵树状结构进行分析,获取节点的内容以及相关属性,或是新增、删除和修改节点的内容。XML 解析器在加载 XML 文件后,DOM 模式将 XML 文件的元素视为一个树状结构的节点,一次性读入内存。
用法举例:
- from xml.dom.minidom import parse
-
- #读取文件
- dom = parse('test.xml')
- #获取文档元素对象
- elem = dom.documentElement
- #获取class
- class_list_obj = elem.getElementsByTagName('class')
- print(class_list_obj) #输出:[
, , ] - print(type(class_list_obj)) #输出:
- for class_element in class_list_obj:
- #获取标签中内容
- code = class_element.getElementsByTagName('code')[0].childNodes[0].nodeValue
- number = class_element.getElementsByTagName('number')[0].childNodes[0].nodeValue
- teacher = class_element.getElementsByTagName('teacher')[0].childNodes[0].nodeValue
- print('code:',code,'number:',number,'teacher:',teacher)
- # 输出:
- # code: 2022001 number: 10 teacher: 小白
- # code: 2022002 number: 20 teacher: 小红
- # code: 2022003 number: 30 teacher: 小黑
doc.wirtexml() :生成xml文档,将创建的存在于内存中的xml文档写入本地硬盘中,这时才能看到新建的xml文档。
函数语法:writexml(file, indent='', addindent='', newl='', encoding=None)
参数说明:
- file:要保存为的文件对象名
- indent:根节点的缩进方式
- addindent:子节点的缩进方式
- newl:针对新行,指明换行方式
- encoding:保存文件的编码方式
用法举例:
- import xml.dom.minidom
-
- #1.在内存中创建一个空的文档
- doc = xml.dom.minidom.Document()
- #2.创建根元素
- root = doc.createElement('collection')
- #3.设置根元素的属性
- root.setAttribute('type','New Arrivals')
- #4.将根节点添加到文档对象中
- doc.appendChild(root)
- #5.创建子元素
- book = doc.createElement('book')
- #6.添加注释
- book.appendChild(doc.createElement('这是一条注释'))
- #7.设置子元素的属性
- book.setAttribute('语言','Python')
- #8.子元素中嵌套元素,并添加文本节点
- name = doc.createElement('name')
- name.appendChild(doc.createTextNode('Python基础'))
- price = doc.createElement('价格')
- price.appendChild(doc.createTextNode('99元'))
- number = doc.createElement('number')
- number.appendChild(doc.createTextNode('剩余66本'))
- #9.将子元素添加到book节点中
- book.appendChild(name)
- book.appendChild(price)
- book.appendChild(number)
- #10.将book节点添加到root根元素中
- root.appendChild(book)
-
- #5-10相同方法,创建子元素
- book = doc.createElement('book')
- #添加注释
- book.appendChild(doc.createElement('这是一条注释'))
- #设置子元素的属性
- book.setAttribute('语言','C++')
- #子元素中嵌套元素,并添加文本节点
- name = doc.createElement('name')
- name.appendChild(doc.createTextNode('C++程序设计'))
- price = doc.createElement('价格')
- price.appendChild(doc.createTextNode('56元'))
- number = doc.createElement('number')
- number.appendChild(doc.createTextNode('剩余100本'))
- #将子元素添加到book节点中
- book.appendChild(name)
- book.appendChild(price)
- book.appendChild(number)
- #将book节点添加到root根元素中
- root.appendChild(book)
-
- print(root.toxml())
- #输出:
<这是一条注释/>Python基础 <价格>99元价格>剩余66本 <这是一条注释/>C++程序设计 <价格>56元价格>剩余100本 - fp =open('./数据.xml','w',encoding='utf-8') #需要指定文件编码格式为 utf-8,不然notepad++中显示十六进制
- doc.writexml(fp, indent='',addindent='\t',newl='\n',encoding='utf-8')
- fp.close()
生成的 数据.xml 文件如下图所示:
使用 Python 向现有的 数据.xml 文件中插入新的子元素。
用法举例:
- import xml.dom.minidom
- from xml.dom.minidom import parse
-
- #对 书籍.xml 新增一个子元素
- xml_file = './数据.xml'
- #拿到根节点
- domTree = parse(xml_file)
- rootNote = domTree.documentElement
- #2.1在内存中创建一个空的文档
- doc = xml.dom.minidom.Document()
- #2.2创建子元素
- book = doc.createElement('book')
- #2.3添加注释
- book.appendChild(doc.createElement('这是一条注释'))
- #2.4设置子元素的属性
- book.setAttribute('语言','matlab')
- #2.5子元素中嵌套元素,并添加文本节点
- name = doc.createElement('name')
- name.appendChild(doc.createTextNode('matlab基础'))
- price = doc.createElement('价格')
- price.appendChild(doc.createTextNode('69元'))
- number = doc.createElement('number')
- number.appendChild(doc.createTextNode('剩余96本'))
- #2.6将子元素添加到book节点中
- book.appendChild(name)
- book.appendChild(price)
- book.appendChild(number)
- #3.找到C++所在位置
- C_book = rootNote.getElementsByTagName('book')[1]
- #4.insertBefore方法,父节点.insertBefore(新节点,父节点中的子节点)
- # rootNote.insertBefore(book,C_book)
- #5.appendChild将新产生的子元素在最后插入
- rootNote.appendChild(book)
- print(rootNote.toxml())
- with open(xml_file, 'w', encoding='utf-8') as f:
- domTree.writexml(f, indent='',addindent='\t', newl='',encoding='utf-8')
- # 输出:
- #
- #
- # <这是一条注释/>
- #
Python基础 - # <价格>99元价格>
- #
剩余66本 - #
- #
- # <这是一条注释/>
- #
C++程序设计 - # <价格>56元价格>
- #
剩余100本 - #
- #
<这是一条注释/>matlab基础 <价格>69元价格>剩余96本
最终得到的 数据.xml 文件如下图所示:
分析:第4和5步代码只能执行一步,默认为后面有效。在 xml 文件中新加入的数据存在格式不统一问题,需要使用 from lxml import etree 模块进行解决。