Python学习之操作XML文件详解

概要

我们经常需要解析用不同语言编写的数据,Python 提供了许多第三方库来解析或拆分用其他语言编写的数据,今天我们来学习下 Python XML 解析器的相关功能。


什么是 XML?

XML 是可扩展标记语言,它在外观上类似于 HTML,但 XML 用于数据表示,而 HTML 用于定义正在使用的数据。XML 专门设计用于在客户端和服务器之间来回发送和接收数据。看看下面的例子:

<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<food>
    <item name="breakfast">Idly</item>
    <price>$2.5</price>
    <description>
   Two idly's with chutney
   </description>
    <calories>553</calories>
</food>
<food>
    <item name="breakfast">Paper Dosa</item>
    <price>$2.7</price>
    <description>
    Plain paper dosa with chutney
    </description>
    <calories>700</calories>
</food>
<food>
    <item name="breakfast">Upma</item>
    <price>$3.65</price>
    <description>
    Rava upma with bajji
    </description>
    <calories>600</calories>
</food>
<food>
    <item name="breakfast">Bisi Bele Bath</item>
    <price>$4.50</price>
    <description>
   Bisi Bele Bath with sev
    </description>
    <calories>400</calories>
</food>
<food>
    <item name="breakfast">Kesari Bath</item>
    <price>$1.95</price>
    <description>
    Sweet rava with saffron
    </description>
    <calories>950</calories>
</food>
</metadata>

上面的示例显示了命名为“Sample.xml”的文件的内容,后面的代码示例都会基于此 XML 例子来进行。

Python XML 解析模块

Python 允许使用两个模块解析这些 XML 文档,即 xml.etree.ElementTree 模块和 Minidom(最小 DOM 实现)。解析意味着从文件中读取信息,并通过识别特定 XML 文件的各个部分将其拆分为多个片段。让我们进一步了解如何使用这些模块来解析 XML 数据。

xml.etree.ElementTree 模块:

该模块帮助我们将 XML 数据格式化为树结构,这是分层数据的最自然表示。元素类型允许在内存中存储分层数据结构,并具有以下属性:

PropertyDescription
Tag一个字符串,表示正在存储的数据类型
Attributes由存储为字典的许多属性组成
Text String包含需要显示的信息的文本字符串
Tail String如有必要,也可以有尾弦
Child Elements由许多存储为序列的子元素组成

ElementTree 是一个封装元素结构并允许与 XML 相互转换的类,现在让我们尝试使用 python 模块解析上述 XML 文件。

有两种方法可以使用ElementTree模块解析文件。

第一个是使用 parse() 函数,第二个是 fromstring() 函数。parse() 函数解析作为文件提供的 XML 文档,而 fromstring 在作为字符串提供时解析 XML,即在三引号内。

使用 parse() 函数:

如前所述,该函数采用文件格式的 XML 进行解析,看看下面的例子:

import xml.etree.ElementTree as ET
mytree = ET.parse('sample.xml')
myroot = mytree.getroot()

我们需要做的第一件事是导入 xml.etree.ElementTree 模块,然后使用 parse() 方法解析“Sample.xml”文件,getroot() 方法返回“Sample.xml”的根元素。

当执行上述代码时,我们不会看到返回的输出,但只要不会有错误就表明代码已成功执行。要检查根元素,可以简单地使用 print 语句,如下所示:

import xml.etree.ElementTree as ET
mytree = ET.parse('sample.xml')
myroot = mytree.getroot()
print(myroot)

Output:

<Element ‘metadata’ at 0x033589F0>

上面的输出表明我们的 XML 文档中的根元素是“元数据”。

使用 fromstring() 函数

我们还可以使用 fromstring() 函数来解析字符串数据,我们需要将 XML 作为三引号内的字符串传递,如下所示:

import xml.etree.ElementTree as ET
data='''<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<food>
    <item name="breakfast">Idly</item>
    <price>$2.5</price>
    <description>
   Two idly's with chutney
   </description>
    <calories>553</calories>
</food>
</metadata>
'''
myroot = ET.fromstring(data)
#print(myroot)
print(myroot.tag)

上面的代码将返回与前一个相同的输出,用作字符串的 XML 文档只是“Sample.xml”的一部分,已将其用于提高可见性,也可以使用完整的 XML 文档。

还可以使用“标签”对象检索根标签,如下所示:

print(myroot.tag)

Output:

metadata

还可以通过仅指定要在输出中看到的字符串部分来对标记字符串输出进行切片。

print(myroot.tag[0:4])

Output:

meta

如前所述,标签也可以具有字典属性。要检查根标签是否有任何属性,您可以使用“attrib”对象,如下所示:

print(myroot.attrib)

Output:

{}

可以看到,输出是一个空字典,因为我们的根标签没有属性。

寻找感兴趣的元素

根也由子标签组成,要检索根标签的子标签,可以使用以下命令:

print(myroot[0].tag)

Output:

food

现在,如果要检索根的所有第一个子标记,可以使用 for 循环对其进行迭代,如下所示:

for x in myroot[0]:
     print(x.tag, x.attrib)

Output:

item {‘name’: ‘breakfast’}
price {}
description {}
calories {}

返回的所有项目都是食物的子属性和标签。

要使用 ElementTree 从 XML 中分离出文本,可以使用 text 属性。例如,如果想检索关于第一个食物的所有信息,应该使用以下代码:

for x in myroot[0]:
        print(x.text)

Output:

Idly
$2.5
Two idly’s with chutney
553

可以看出,第一项的文本信息已作为输出返回。现在如果想以特定价格显示所有商品,可以使用 get() 方法,此方法访问元素的属性。

for x in myroot.findall('food'):
    item =x.find('item').text
    price = x.find('price').text
    print(item, price)

Output:

Idly $2.5
Paper Dosa $2.7
Upma $3.65
Bisi Bele Bath $4.50
Kesari Bath $1.95

上面的输出显示了所有必需的项目以及每个项目的价格,使用 ElementTree,还可以修改 XML 文件。

修改 XML 文件

我们的 XML 文件中的元素是可以被操纵的,为此,可以使用 set() 函数。让我们先来看看如何在 XML 中添加一些东西。

添加到 XML:

以下示例显示了如何在项目描述中添加内容。

for description in myroot.iter('description'):
     new_desc = str(description.text)+'wil be served'
     description.text = str(new_desc)
     description.set('updated', 'yes')
 
mytree.write('new.xml')

write() 函数有助于创建一个新的 xml 文件并将更新的输出写入该文件,但是也可以使用相同的功能修改原始文件。执行上述代码后,将能够看到已创建一个包含更新结果的新文件。

要添加新的子标签,可以使用 SubElement() 方法。例如,如果想在第一项 Idly 中添加新的专业标签,可以执行以下操作:

ET.SubElement(myroot[0], 'speciality')
for x in myroot.iter('speciality'):
     new_desc = 'South Indian Special'
     x.text = str(new_desc)
 
mytree.write('output5.xml')

就像我们所见到的,在第一个食物标签下添加了一个新标签。可以通过在 [] 括号内指定下标来在任意位置添加标签。

下面让我们看看如何使用这个模块删除项目。

从 XML 中删除:

要使用 ElementTree 删除属性或子元素,可以使用 pop() 方法,此方法将删除用户不需要的所需属性或元素。

myroot[0][0].attrib.pop('name', None)
 
# create a new XML file with the results
mytree.write('output5.xml')

Output:

cfac6e9c819e4d6eaeac5bb6b87933ea.jpg 上图显示 name 属性已从 item 标记中删除。要删除完整的标签,可以使用相同的 pop() 方法,如下所示:

myroot[0].remove(myroot[0][0])
mytree.write('output6.xml')

Output:

c6d49b3582fd4f12af7b9c3bdb4bbdb6.jpg

 输出显示食品标签的第一个子元素已被删除。如果要删除所有标签,可以使用 clear() 函数,如下所示:

myroot[0].clear()
mytree.write('output7.xml')

执行上述代码时,food 标签的第一个子标签将被完全删除,包括所有子标签。

到目前为止,我们一直在使用 Python XML 解析器中的 xml.etree.ElementTree 模块。现在让我们看看如何使用 Minidom 解析 XML。

xml.dom.minidom Module

该模块基本上是由精通DOM(文档对象模块)的人使用的,DOM 应用程序通常首先将 XML 解析为 DOM。在 xml.dom.minidom 中,可以通过以下方式实现

使用 parse() 函数:

第一种方法是通过提供要解析的 XML 文件作为参数来使用 parse()函数。例如:

from xml.dom import minidom
p1 = minidom.parse("sample.xml")

执行此操作后,将能够拆分 XML 文件并获取所需的数据。还可以使用此函数解析打开的文件。

dat=open('sample.xml')
p2=minidom.parse(dat)

在这种情况下,存储打开文件的变量作为参数提供给 parse 函数。

使用 parseString() 方法:

当我们想要提供要作为字符串解析的 XML 时使用此方法。

p3 = minidom.parseString('<myxml>Using<empty/> parseString</myxml>')

可以使用上述任何方法解析 XML,现在让我们尝试使用这个模块获取数据

寻找感兴趣的元素

在我的文件被解析后,如果我们尝试打印它,返回的输出会显示一条消息,即存储解析数据的变量是 DOM 的对象。

dat=minidom.parse('sample.xml')
print(dat)

Output:

<xml.dom.minidom.Document object at 0x03B5A308>

使用 GetElementsByTagName 访问元素

tagname= dat.getElementsByTagName('item')[0]
print(tagname)

如果我们尝试使用 GetElementByTagName 方法获取第一个元素,我将看到以下输出:

<DOM Element: item at 0xc6bd00>

请注意,只返回了一个输出,因为为方便起见,这里使用了 [0] 下标,这将在进一步的示例中被删除。

要访问属性的值,我们将不得不使用 value 属性,如下所示:

dat = minidom.parse('sample.xml')
tagname= dat.getElementsByTagName('item')
print(tagname[0].attributes['name'].value)

Output:

breakfast

要检索这些标签中存在的数据,可以使用 data 属性,如下所示:

print(tagname[1].firstChild.data)

Output:

Paper Dosa

还可以使用 value 属性拆分和检索属性的值。

print(items[1].attributes['name'].value)

Output:

breakfast

要打印出我们菜单中的所有可用项目,可以遍历这些项目并返回所有项目。

for x in items:
    print(x.firstChild.data)

Output:

Idly
Paper Dosa
Upma
Bisi Bele Bath
Kesari Bath

要计算我们菜单上的项目数,可以使用 len() 函数,如下所示:

print(len(items))

Output:

5

输出指定我们的菜单包含 5 个项目。

 

今天的分享就到这里,喜欢的朋友可以点赞收藏转发,感谢🙏 

---END---

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/80377.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于IDE Eval Resetter延长IntelliJ IDEA等软件试用期的方法(包含新版本软件的操作方法)

本文介绍基于IDE Eval Resetter插件&#xff0c;对集成开发环境IntelliJ IDEA等JetBrains公司下属的多个开发软件&#xff0c;加以试用期延长的方法。 我们这里就以IntelliJ IDEA为例&#xff0c;来介绍这一插件发挥作用的具体方式。不过&#xff0c;需要说明使用IDE Eval Rese…

CentOS系统环境搭建(五)——Centos7安装maven

centos系统环境搭建专栏&#x1f517;点击跳转 Centos7安装maven 下载压缩包 maven下载官网 解压 压缩包放置到/usr/local tar -xvf apache-maven-3.9.2-bin.tar.gz配置环境变量 vim /etc/profile在最下面追加 MAVEN_HOME/usr/local/apache-maven-3.9.2 export PATH${MAV…

vscode ssh 远程 gdb 调试

一、点运行与调试&#xff0c;生成launch.json 文件 二、点添加配置&#xff0c;选择GDB 三、修改启动程序路径

迈向通用听觉人工智能!清华电子系、火山语音携手推出认知导向的听觉大语言模型SALMONN

日前&#xff0c;清华大学电子工程系与火山语音团队携手合作&#xff0c;推出认知导向的开源听觉大语言模型SALMONN (Speech Audio Language Music Open Neural Network)。 大语言模型 SALMONN LOGO 相较于仅仅支持语音输入或非语音音频输入的其他大模型&#xff0c;SALMONN对…

ReentrantLock源码解析

定义 可重入锁&#xff0c;对于同一个线程可以重复获得此锁。分为FailLock和NonfairLock。 加锁就是将exclusiveOwnerThread设置为当前线程&#xff0c;且将status加一&#xff0c;解锁就status-1&#xff0c;且exclusiveOwnerThread设置为null。 公平锁&#xff1a;根据先来后…

【Hibench 】完成 HDP-Spark 性能测试

&#x1f341; 博主 "开着拖拉机回家"带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——&#x1f390;开着拖拉机回家_Linux,Java基础学习,大数据运维-CSDN博客 &#x1f390;✨&#x1f341; &#x1fa81;&#x1f341; 希望本文能够给您带来一定的…

首发 | FOSS分布式全闪对象存储系统白皮书

一、 产品概述 1. 当前存储的挑战 随着云计算、物联网、5G、大数据、人工智能等新技术的飞速发展&#xff0c;数据呈现爆发式增长&#xff0c;预计到2025年中国数据量将增长到48.6ZB&#xff0c;超过80%为非结构化数据。 同时&#xff0c;数字经济正在成为我国经济发展的新…

Mathematica(42)-计算N个数值的和

比如&#xff0c;我们要用Mathematica求得到下面的式子&#xff1a; 这就需要用到一个函数&#xff1a;Sum 具体地&#xff0c;Sum函数的使用形式如下&#xff1a; 因此&#xff0c;按照公式就可以得到下面的结果&#xff1a; 如果&#xff0c;我们想要将求和号也加进去&#…

广州华锐互动:3D数字孪生开发编辑器助力企业高效开发数字孪生应用

3D数字孪生开发编辑器是一种新兴的技术&#xff0c;它可以帮助企业更好地管理和维护其物联网设备。这些工具可以帮助企业实现对设备的实时监控、故障排除和优化&#xff0c;从而提高生产效率和降低成本。 数字孪生系统是一种将物理世界与数字世界相结合的技术&#xff0c;它可以…

未来公文的智能化进程

随着技术的飞速发展&#xff0c;公文——这个有着悠久历史的官方沟通方式&#xff0c;也正逐步走向智能化的未来。自动化、人工智能、区块链...这些现代科技正重塑我们的公文制度&#xff0c;让其变得更加高效、安全和智慧。 1.语义理解与自动生成 通过深度学习和NLP&#xff…

04_15页表缓存(TLB)和巨型页

前言 linux里面每个物理内存(RAM)页的一般大小都是4kb(32位就是4kb),为了使管理虚拟地址数变少 加快从虚拟地址到物理地址的映射 建议配值并使用HugePage巨型页特性 cpu和mmu和页表缓存(TLB)和cache和ram的关系 CPU看到的都是虚拟地址&#xff0c;需要经过MMU的转化&#xf…

vue3 injection报错 injection“xxx“ not found.

在封装CheckboxGroup组件的的时候&#xff0c;需要通过provide&#xff0c;代码如下&#xff1a; //父组件 <template><div class"envCheckBoxGroup"><slot></slot></div> </template> <script setup> import { provide …

使用SSH隧道将Ubuntu云服务器Jupyter Notebook端口映射到本地

本文主要实现了在Ubuntu云服务器后台运行Jupyter Notebook&#xff0c;并使用SSH隧道将服务器端口映射到本地 1. 生成配置文件 运行以下命令生成Jupyter Notebook的配置文件&#xff1a; jupyter notebook --generate-config这将在用户主目录下生成一个名为.jupyter的文件夹&…

大数据Flink(六十四):Flink运行时架构介绍

文章目录 Flink运行时架构介绍 一、系统架构 二、​​​​​​​​​​​​​​整体构成 三、作业管理器&#xff08;JobManager&#xff09; 四、任务管理器&#xff08;TaskManager&#xff09; Flink运行时架构介绍 我们已经对 Flink 的主要特性和部署提交有了基本的了…

AI绘画 | 一文学会Midjourney绘画,创作自己的AI作品(快速入门+参数介绍)

一、生成第一个AI图片 首先&#xff0c;生成将中文描述词翻译成英文 然后在输入端输入&#xff1a;/imagine prompt:Bravely running boy in Q version, cute head portrait 最后&#xff0c;稍等一会即可输出效果 说明&#xff1a; 下面的U1、U2、U3、U4代表的第一张、第二张…

HCIP第五节------------------------------------------ospf

一、OSPF基础 1、动态路由分类 2、距离矢量协议 运行距离矢量路由协议的路由器周期性地泛洪自己的路由表。通过路由的交互&#xff0c;每台路由器都从相邻的路由器学习到路由&#xff0c;并且加载进自己的路由表中&#xff0c;然后再通告给其他相邻路由器。 对于网络中的所有…

模型预测笔记(一):数据清洗分析及可视化、模型搭建、模型训练和预测代码一体化和对应结果展示(可作为baseline)

模型预测 一、导入关键包二、如何载入、分析和保存文件三、修改缺失值3.1 众数3.2 平均值3.3 中位数3.4 0填充 四、修改异常值4.1 删除4.2 替换 五、数据绘图分析5.1 饼状图5.1.1 绘制某一特征的数值情况&#xff08;二分类&#xff09; 5.2 柱状图5.2.1 单特征与目标特征之间的…

《Java极简设计模式》第03章:工厂方法模式(FactoryMethod)

作者&#xff1a;冰河 星球&#xff1a;http://m6z.cn/6aeFbs 博客&#xff1a;https://binghe.gitcode.host 文章汇总&#xff1a;https://binghe.gitcode.host/md/all/all.html 源码地址&#xff1a;https://github.com/binghe001/java-simple-design-patterns/tree/master/j…

【路由协议】使用按需路由协议和数据包注入的即时网络模拟传递率(PDR)、总消耗能量和节点消耗能量以及延迟研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

opencv直方图与模板匹配

import cv2 #opencv读取的格式是BGR import numpy as np import matplotlib.pyplot as plt#Matplotlib是RGB %matplotlib inline def cv_show(img,name):cv2.imshow(name,img)cv2.waitKey()cv2.destroyAllWindows() 直方图 cv2.calcHist(images,channels,mask,histSize,ran…