面试官问我:如何在 Python 中解析和修改 XML
摘要:我们经常需要解析用不同语言编写的数据。Python提供了许多库来解析或拆分用其他语言编写的数据。在此 Python XML 解析器教程中,您将学习如何使用 Python 解析 XML。
本文分享自华为云社区《从零开始学python | 如何在 Python 中解析和修改 XML?》,原文作者:Yuchuan。
我们经常需要解析用不同语言编写的数据。Python提供了许多库来解析或拆分用其他语言编写的数据。在此 Python XML 解析器教程中,您将学习如何使用 Python 解析 XML。
以下是本教程中涵盖的所有主题:
What is XML?
Python XML Parsing Modules
xml.etree.ElementTree Module
- Using parse() function
- Using fromstring() function
- Finding Elements of Interest
- Modifying XML files
- Adding to XML
- Deleting from XML
xml.dom.minidom Module
- Using parse() function
- Using fromString() function
- Finding Elements of Interest
让我们开始吧。:)
什么是 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>
两个 idly's with chutney
< /description>
<calories> 553 </calories>
</food>
<food>
<item name ="breakfast" > Paper Dosa </item>
<price> $2.7 </price>
<
<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>
藏红花甜拉瓦
</description>
<calories> 950 </calories>
</食物>
</元数据>
上面的示例显示了我命名为“Sample.xml”的文件的内容,我将在此 Python XML 解析器教程中为所有即将推出的示例使用相同的内容。
Python XML 解析模块
Python允许使用两个模块解析这些 XML 文档,即 xml.etree.ElementTree 模块和 Minidom(最小 DOM 实现)。解析意味着从文件中读取信息并通过识别该特定 XML 文件的部分将其拆分为多个部分。让我们进一步了解如何使用这些模块来解析 XML 数据。
xml.etree.ElementTree 模块:
该模块帮助我们在树结构中格式化 XML 数据,这是分层数据的最自然表示。元素类型允许在内存中存储分层数据结构,并具有以下属性:

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)
输出: <元素'元数据'在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)
输出: 元数据
您还可以通过指定要在输出中看到的字符串部分来对标签字符串输出进行切片。
例子:
print(myroot.tag[0:4])
输出: 元
如前所述,标签也可以具有字典属性。要检查根标记是否具有任何属性,您可以使用“attrib”对象,如下所示:
例子:
print(myroot.attrib)
输出: {}
如您所见,输出是一个空字典,因为我们的根标签没有属性。
寻找感兴趣的元素:
根也由子标签组成。要检索根标记的子项,您可以使用以下命令:
例子:
print(myroot[0].tag)
输出:食物
现在,如果要检索根的所有第一个子标签,可以使用 for 循环迭代它,如下所示:
例子:
for x in myroot[0]:
print(x.tag, x.attrib)
输出:
item {'name': 'breakfast'}
价格 {}
描述 {}
卡路里 {}
返回的所有项目都是食物的子属性和标签。
要使用 ElementTree 将文本从 XML 中分离出来,您可以使用 text 属性。例如,如果我想检索有关第一个食品的所有信息,我应该使用以下代码:
例子:
for x in myroot[0]:
print(x.text)
输出:
懒懒地
$ 2.5
两悠闲地与酸辣酱的
553
可以看到,第一项的文本信息已经作为输出返回了。现在,如果您想显示具有特定价格的所有商品,您可以使用 get() 方法。此方法访问元素的属性。
例子:
for x in myroot.findall('food'):
item =x.find('item').text
price = x.find('price').text
print(item, price)
输出:
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')
输出:

上图显示name属性已从item标记中删除。要删除完整的标签,您可以使用相同的 pop() 方法,如下所示:
例子:
myroot[0].remove(myroot[0][0])
mytree.write('output6.xml')
输出:

输出显示食品标签的第一个子元素已被删除。如果要删除所有标签,可以使用 clear() 函数,如下所示:
例子:
myroot[0].clear()
mytree.write('output7.xml')
输出:
执行上述代码时,food 标签的第一个子标签将被完全删除,包括所有子标签。到这里为止,我们一直在使用这个 Python XML 解析器教程中的 xml.etree.ElementTree 模块。现在让我们看看如何使用 Minidom 解析 XML。
xml.dom.minidom模块:
这个模块基本上是由精通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)
在这种情况下,存储打开文件的变量作为参数提供给解析函数。
使用 parseString() 方法:
当您想要提供要作为字符串解析的 XML 时,将使用此方法。
例子:
p3 = minidom.parseString('<myxml>Using<empty/> parseString</myxml>')
您可以使用上述任何一种方法来解析 XML。现在让我们尝试使用此模块获取数据。
寻找感兴趣的元素:
在我的文件被解析后,如果我尝试打印它,返回的输出会显示一条消息,表明存储解析数据的变量是 DOM 对象。
例子:
dat=minidom.parse('sample.xml')
print(dat)
输出:
<xml.dom.minidom.Document 对象在 0x03B5A308>
使用 GetElementByTagName 访问元素:
例子:
tagname= dat.getElementsByTagName('item')[0]
print(tagname)
如果我尝试使用 GetElementByTagName 方法获取第一个元素,我将看到以下输出:
输出:
<DOM 元素:0xc6bd00 处的项目>
请注意,只返回了一个输出,因为为了方便我使用了 [0] 下标,这将在进一步的示例中删除。
要访问属性的值,我必须按如下方式使用 value 属性:
例子:
dat = minidom.parse('sample.xml')
tagname= dat.getElementsByTagName('item')
print(tagname[0].attributes['name'].value)
输出: 早餐
要检索这些标签中存在的数据,您可以使用 data 属性,如下所示:
例子:
print(tagname[1].firstChild.data)
输出: 纸 Dosa
您还可以使用value属性拆分和检索属性的值。
例子:
print(items[1].attributes['name'].value)
输出: 早餐
要打印出我们菜单中可用的所有项目,您可以遍历这些项目并返回所有项目。
例子:
for x in items:
print(x.firstChild.data)
输出:
袖手旁观
纸DOSA
UPMA
碧斯百丽沐浴
Kesari浴
要计算菜单上的项目数,您可以使用 len() 函数,如下所示:
例子:
print(len(items))
输出指定我们的菜单包含 5 个项目。
这使我们结束了本 Python XML 解析器教程。我希望你已经清楚地了解了一切。
面试官问我:如何在 Python 中解析和修改 XML的更多相关文章
- 如何在FineReport中解析数据库内XML文件
在数据库表中,其中字段XML所存的为xml格式数据在表xmltest中.那么在使用该表进行报表制作时,需要将存于xml字段中的值读取出来作为报表数据源. XML每条记录数据格式如下: <Fiel ...
- 【Java8新特性】面试官问我:Java8中创建Stream流有哪几种方式?
写在前面 先说点题外话:不少读者工作几年后,仍然在使用Java7之前版本的方法,对于Java8版本的新特性,甚至是Java7的新特性几乎没有接触过.真心想对这些读者说:你真的需要了解下Java8甚至以 ...
- 美女面试官问我Python如何优雅的创建临时文件,我的回答....
[摘要] 本故事纯属虚构,如有巧合,他们故事里的美女面试官也肯定没有我的美,请自行脑补... 小P像多数Python自学者一样,苦心钻研小半年,一朝出师投简历. 这不,一家招聘初级Python开发工程 ...
- 面试官问我,Redis分布式锁如何续期?懵了。
前言 上一篇[面试官问我,使用Dubbo有没有遇到一些坑?我笑了.]之后,又有一位粉丝和我说在面试过程中被虐了.鉴于这位粉丝是之前肥朝的粉丝,而且周一又要开启新一轮的面试,为了回馈他长期以来的支持,所 ...
- 面试官问,说一个你在工作非常有价值的bug
如果你去参考面试,做足了准备,面对面试官员从容不迫,吐沫横飞的大谈自己的工作经历.突然,面试官横插一句:说一个你在工作非常有价值的bug.顿时,整个空气都仿佛都凝固了!“What?”... 我想没几个 ...
- 面试官问:JS的this指向
前言 面试官出很多考题,基本都会变着方式来考察this指向,看候选人对JS基础知识是否扎实.读者可以先拉到底部看总结,再谷歌(或各技术平台)搜索几篇类似文章,看笔者写的文章和别人有什么不同(欢迎在评论 ...
- 面试官问你JS基本类型时他想知道什么?
面试的时候我们经常会被问答js的数据类型.大部分情况我们会这样回答包括:1.基本类型(值类型或者原始类型): Number.Boolean.String.NULL.Undefined以及ES6的Sym ...
- 面试官问线程安全的List,看完再也不怕了!
最近在Java技术栈知识星球里面有球友问到了线程安全的 List: 扫码查看答案或加入知识星球 栈长在之前的文章<出场率比较高的一道多线程安全面试题>里面讲过 ArrayList 的不安全 ...
- 美团面试官问我一个字符的String.length()是多少,我说是1,面试官说你回去好好学一下吧
本文首发于微信公众号:程序员乔戈里 public class testT { public static void main(String [] args){ String A = "hi你 ...
随机推荐
- IP Networks UVA - 1590
Alex is administrator of IP networks. His clients have a bunch of individual IP addresses and he de ...
- 光猫和路由器都支持ipv6,却无法使用ipv6?
这些年很多地方的光猫都能获得ipv6地址了,而且新出的路由基本都支持ipv6,但是还是有很多人在http://test-ipv6.com看不到自己的ipv6地址,也上不了ipv6网站. 我也遇到这个问 ...
- Ubuntu20.04安装MongoDB
本教程描述了如何在Ubuntu20.04上安装MongoDB4.4 安装MongoDB Ubuntu 20.04默认存储库中不提供最新版本的MongoDB,因此需要在系统中添加官方的MongoDB存储 ...
- Nginx 配置浏览Linux 系统目录并下载文件
准备工作: 安装编译工具及库文件: yum -y install make zlib zlib-devel gcc-c++ libtool openssl openssl-devel 安装PCRE( ...
- 过 DNF TP 驱动保护(二)
过 DNF TP 驱动保护(二) 文章目录: 01. 博文简介: 02. 环境及工具准备: 03. 分析 TP 所做的保护: 04. 干掉 NtOpenProc ...
- hdu4915 判断括号匹配
题意: 问你括号匹配是否唯一,三种字符'(','?',')',问号可以变成任何字符. 思路: 首先我们要学会判断当前串是否成立?怎么判断?我的方法是跑两遍,开三个变变量 s1 ...
- UVA11078开放式学分制(前面-后面的最大值)
题意: 给你一个长度为n的整数序列a0 a1 a2..找出两个整数ai,aj(i<j),使得ai-aj最大. 思路: 简单题目,想象一下,对于每一个数我们只要用他前面的最 ...
- Bugku-flag.php
flag.php 目录 flag.php 题目描述 解题过程 题目描述 点了login咋没反应 提示:hint 解题过程 fuzz 打开发现是个登录页面,点击login没反应,看了源码,action= ...
- left join 后用 on 还是 where,区别大了!
前天写SQL时本想通过 A left B join on and 后面的条件来使查出的两条记录变成一条,奈何发现还是有两条. 后来发现 join on and 不会过滤结果记录条数,只会根据and后的 ...
- Day015 异常处理机制
异常处理机制 抛出异常 捕获异常 异常处理的五个关键字 try:监控一个代码块,有异常就能通过catch捕获 catch(想要捕获的异常类型):捕获想要捕获的异常,catch代码块的代码只有在捕获到异 ...