python【模块】xml.etree.ElementTree 解析 xml(1)

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: python【模块】xml.etree.ElementTree 解析 xml(1)

pytho 模块 xml.etree.ElementTree 解析 xml

文章目录

pytho 模块 xml.etree.ElementTree 解析 xml

1. 什么是 XML?

2. ElementTree 简介

3. 解析 XML 数据

示例

4. For 循环

5. XPath 表达式

6. 修改 XML

7. 修复属性

8. 移动元素

9. 构建 XML 文档

10. 结论

1. 什么是 XML?

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


XML 创建了一种易于解释并支持层次结构的树状结构。只要页面遵循 XML,就可以将其称为 XML 文档。


XML 文档具有称为元素的部分,由开始和结束标记定义。标签是一种以 开头<和结尾的标记结构>。开始标签和结束标签之间的字符(如果有的话)是元素的内容。元素可以包含标记,包括其他元素,称为“子元素”。

最大的顶级元素称为root,它包含所有其他元素。

属性是存在于起始标签或空元素标签中的名称-值对。XML 属性只能有一个值,并且每个属性在每个元素上最多只能出现一次。

XML 文件:

<?xml version="1.0"?>
<collection>
    <genre category="Action">
        <decade years="1980s">
            <movie favorite="True" title="Indiana Jones: The raiders of the lost Ark">
                <format multiple="No">DVD</format>
                <year>1981</year>
                <rating>PG</rating>
                <description>
                'Archaeologist and adventurer Indiana Jones 
                is hired by the U.S. government to find the Ark of the 
                Covenant before the Nazis.'
                </description>
            </movie>
               <movie favorite="True" title="THE KARATE KID">
               <format multiple="Yes">DVD,Online</format>
               <year>1984</year>
               <rating>PG</rating>
               <description>None provided.</description>
            </movie>
            <movie favorite="False" title="Back 2 the Future">
               <format multiple="False">Blu-ray</format>
               <year>1985</year>
               <rating>PG</rating>
               <description>Marty McFly</description>
            </movie>
        </decade>
        <decade years="1990s">
            <movie favorite="False" title="X-Men">
               <format multiple="Yes">dvd, digital</format>
               <year>2000</year>
               <rating>PG-13</rating>
               <description>Two mutants come to a private academy for their kind whose resident superhero team must 
               oppose a terrorist organization with similar powers.</description>
            </movie>
            <movie favorite="True" title="Batman Returns">
               <format multiple="No">VHS</format>
               <year>1992</year>
               <rating>PG13</rating>
               <description>NA.</description>
            </movie>
               <movie favorite="False" title="Reservoir Dogs">
               <format multiple="No">Online</format>
               <year>1992</year>
               <rating>R</rating>
               <description>WhAtEvER I Want!!!?!</description>
            </movie>
        </decade>    
    </genre>
    <genre category="Thriller">
        <decade years="1970s">
            <movie favorite="False" title="ALIEN">
                <format multiple="Yes">DVD</format>
                <year>1979</year>
                <rating>R</rating>
                <description>"""""""""</description>
            </movie>
        </decade>
        <decade years="1980s">
            <movie favorite="True" title="Ferris Bueller's Day Off">
                <format multiple="No">DVD</format>
                <year>1986</year>
                <rating>PG13</rating>
                <description>Funny movie about a funny guy</description>
            </movie>
            <movie favorite="FALSE" title="American Psycho">
                <format multiple="No">blue-ray</format>
                <year>2000</year>
                <rating>Unrated</rating>
                <description>psychopathic Bateman</description>
            </movie>
        </decade>
    </genre>

从您上面阅读的内容中,您可以看到


<collection>是单个根元素:它包含所有其他元素,例如<genre>、 或<movie>,它们是子元素或子元素。如您所见,这些元素是嵌套的。

这些子元素也可以充当父元素并包含它们自己的子元素,这些子元素称为“子子元素”。例如,您会看到<movie>元素包含几个“属性”,例如favorite title提供更多信息!

2. ElementTree 简介

到目前为止,您所了解的 XML 解析器可以完成这项工作。但是,它们不太符合 Python 的哲学,这绝非偶然。虽然 DOM 遵循 W3C 规范,而 SAX 是根据 Java API 建模的,但两者都没有特别像 Python 的感觉。


更糟糕的是,DOM 和 SAX 解析器都感觉过时了,因为它们在CPython解释器中的一些代码已经超过 20 年没有改变了!在撰写本文时,它们的实现仍然不完整,并且缺少 typeshed 存根,这会破坏代码编辑器中的代码完成。


同时,Python 2.5 带来了解析和编写 XML 文档的全新视角——ElementTree API。它是一个轻量级、高效、优雅且功能丰富的界面,甚至一些第三方库也以此为基础。要开始使用它,您必须导入xml.etree.ElementTree模块,这有点拗口。因此,习惯上这样定义别名:

import xml.etree.ElementTree as ET

您可以通过采用不同的解析策略来使用 ElementTree API:

1671099061720.png

3. 解析 XML 数据

提供的 XML 文件中,有一个描述的电影的基本集合。唯一的问题是数据很乱!这个集合有很多不同的策展人,每个人都有自己的方式将数据输入文件。本教程的主要目标是使用 Python 阅读和理解文件 - 然后解决问题。

首先,您需要使用ElementTree.

tree = ET.parse('movies.xml')
root = tree.getroot()

现在您已经初始化了树,您应该查看 XML 并打印出值以了解树的结构。


树的每个部分(包括根)都有一个描述元素的标签。此外,正如您在介绍中看到的那样,元素可能具有属性,这些属性是附加的描述符,特别用于重复标记的使用。属性还有助于验证为该标记输入的值,再次有助于 XML 的结构化格式。

root.tag
输出:
'collection'

在顶层,您会看到此 XML 植根于collection标记中。

root.attrib
输出:
{}

所以根没有属性。

示例

xml:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
    <!ENTITY custom_entity "Hello">
]>
<svg xmlns="http://www.w3.org/2000/svg"
  xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
  viewBox="-105 -100 210 270" width="210" height="270">
  <inkscape:custom x="42" inkscape:z="555">Some value</inkscape:custom>
  <defs>
    <linearGradient id="skin" x1="0" x2="0" y1="0" y2="1">
      <stop offset="0%" stop-color="yellow" stop-opacity="1.0"/>
      <stop offset="75%" stop-color="gold" stop-opacity="1.0"/>
      <stop offset="100%" stop-color="orange" stop-opacity="1"/>
    </linearGradient>
  </defs>
  <g id="smiley" inkscape:groupmode="layer" inkscape:label="Smiley">
    <!-- Head -->
    <circle cx="0" cy="0" r="50"
      fill="url(#skin)" stroke="orange" stroke-width="2"/>
    <!-- Eyes -->
    <ellipse cx="-20" cy="-10" rx="6" ry="8" fill="black" stroke="none"/>
    <ellipse cx="20" cy="-10" rx="6" ry="8" fill="black" stroke="none"/>
    <!-- Mouth -->
    <path d="M-20 20 A25 25 0 0 0 20 20"
      fill="white" stroke="black" stroke-width="3"/>
  </g>
  <text x="-40" y="75">&custom_entity; &lt;svg&gt;!</text>
  <script>
    <![CDATA[
      console.log("CDATA disables XML parsing: <svg>")
      const smiley = document.getElementById("smiley")
      const eyes = document.querySelectorAll("ellipse")
      const setRadius = r => e => eyes.forEach(x => x.setAttribute("ry", r))
      smiley.addEventListener("mouseenter", setRadius(2))
      smiley.addEventListener("mouseleave", setRadius(8))
    ]]>
  </script>
</svg>
>>> import xml.etree.ElementTree as ET
>>> tree = ET.parse('movies.xml')
>>> root = tree.getroot()
>>> element = root[0]
>>> element.tag
'{http://www.inkscape.org/namespaces/inkscape}custom'
>>> element.text
'Some value'
>>> element.attrib
{'x': '42', '{http://www.inkscape.org/namespaces/inkscape}z': '555'}
>>> element.get("x")
'42'

4. For 循环

通过使用简单的“for”循环,您可以轻松地迭代根中的子元素(通常称为“子元素”)。

for child in root:
    print(child.tag, child.attrib)

输出:

genre {'category': 'Action'}
genre {'category': 'Thriller'}
genre {'category': 'Comedy'}

现在你知道根的孩子collection都是genre. 为了指定类型,XML 使用属性category。genre根据元素,有Action, Thriller, and Comedy movies。


通常,了解整个树中的所有元素会很有帮助。一个有用的功能是root.iter()。您可以将此函数放入“for”循环中,它将遍历整个树。

[elem.tag for elem in root.iter()]

输出:

['collection',
 'genre',
 'decade',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'decade',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'genre',
 'decade',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'decade',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'genre',
 'decade',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'decade',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'decade',
 'movie',
 'format',
 'year',
 'rating',
 'description',
 'decade',
 'movie',
 'format',
 'year',
 'rating',
 'description']

这给出了您拥有多少个元素的一般概念,但它不显示树中的属性或级别。


有一种有用的方法可以查看整个文档。任何元素都有.tostring()方法。如果将根传递给.tostring()方法,则可以返回整个文档。在ElementTree(记住别名为ET)内,.tostring()采用一种稍微奇怪的形式。


由于ElementTree它是一个功能强大的库,不仅可以解释 XML,因此您必须将要显示的文档的编码和解码都指定为字符串。对于 XML,使用’utf8’- 这是 XML 的典型文档格式类型。

print(ET.tostring(root, encoding='utf8').decode('utf8'))

输出:

<?xml version='1.0' encoding='utf8'?>
<collection>
    <genre category="Action">
        <decade years="1980s">
            <movie favorite="True" title="Indiana Jones: The raiders of the lost Ark">
                <format multiple="No">DVD</format>
                <year>1981</year>
                <rating>PG</rating>
                <description>
                'Archaeologist and adventurer Indiana Jones 
                is hired by the U.S. government to find the Ark of the 
                Covenant before the Nazis.'
                </description>
            </movie>
               <movie favorite="True" title="THE KARATE KID">
               <format multiple="Yes">DVD,Online</format>
               <year>1984</year>
               <rating>PG</rating>
               <description>None provided.</description>
            </movie>
            <movie favorite="False" title="Back 2 the Future">
               <format multiple="False">Blu-ray</format>
               <year>1985</year>
               <rating>PG</rating>
               <description>Marty McFly</description>
            </movie>
        </decade>
        <decade years="1990s">
            <movie favorite="False" title="X-Men">
               <format multiple="Yes">dvd, digital</format>
               <year>2000</year>
               <rating>PG-13</rating>
               <description>Two mutants come to a private academy for their kind whose resident superhero team must 
               oppose a terrorist organization with similar powers.</description>
            </movie>
            <movie favorite="True" title="Batman Returns">
               <format multiple="No">VHS</format>
               <year>1992</year>
               <rating>PG13</rating>
               <description>NA.</description>
            </movie>
               <movie favorite="False" title="Reservoir Dogs">
               <format multiple="No">Online</format>
               <year>1992</year>
               <rating>R</rating>
               <description>WhAtEvER I Want!!!?!</description>
            </movie>
        </decade>    
    </genre>
    <genre category="Thriller">
        <decade years="1970s">
            <movie favorite="False" title="ALIEN">
                <format multiple="Yes">DVD</format>
                <year>1979</year>
                <rating>R</rating>
                <description>"""""""""</description>
            </movie>
        </decade>
        <decade years="1980s">
            <movie favorite="True" title="Ferris Bueller's Day Off">
                <format multiple="No">DVD</format>
                <year>1986</year>
                <rating>PG13</rating>
                <description>Funny movie about a funny guy</description>
            </movie>
            <movie favorite="FALSE" title="American Psycho">
                <format multiple="No">blue-ray</format>
                <year>2000</year>
                <rating>Unrated</rating>
                <description>psychopathic Bateman</description>
            </movie>
        </decade>
    </genre>
    <genre category="Comedy">
        <decade years="1960s">
            <movie favorite="False" title="Batman: The Movie">
                <format multiple="Yes">DVD,VHS</format>
                <year>1966</year>
                <rating>PG</rating>
                <description>What a joke!</description>
            </movie>
        </decade>
        <decade years="2010s">
            <movie favorite="True" title="Easy A">
                <format multiple="No">DVD</format>
                <year>2010</year>
                <rating>PG--13</rating>
                <description>Emma Stone = Hester Prynne</description>
            </movie>
            <movie favorite="True" title="Dinner for SCHMUCKS">
                <format multiple="Yes">DVD,digital,Netflix</format>
                <year>2011</year>
                <rating>Unrated</rating>
                <description>Tim (Rudd) is a rising executive
                 who “succeeds” in finding the perfect guest, 
                 IRS employee Barry (Carell), for his boss’ monthly event, 
                 a so-called “dinner for idiots,” which offers certain 
                 advantages to the exec who shows up with the biggest buffoon.
                 </description>
            </movie>
        </decade>
        <decade years="1980s">
            <movie favorite="False" title="Ghostbusters">
                <format multiple="No">Online,VHS</format>
                <year>1984</year>
                <rating>PG</rating>
                <description>Who ya gonna call?</description>
            </movie>
        </decade>
        <decade years="1990s">
            <movie favorite="True" title="Robin Hood: Prince of Thieves">
                <format multiple="No">Blu_Ray</format>
                <year>1991</year>
                <rating>Unknown</rating>
                <description>Robin Hood slaying</description>
            </movie>
        </decade>
    </genre>
</collection>

您可以扩展该iter()函数的使用,以帮助查找感兴趣的特定元素。root.iter()将列出根下与指定元素匹配的所有子元素。在这里,您将列出movie树中元素的所有属性:

for movie in root.iter('movie'):
    print(movie.attrib)

输出:

{'favorite': 'True', 'title': 'Indiana Jones: The raiders of the lost Ark'}
{'favorite': 'True', 'title': 'THE KARATE KID'}
{'favorite': 'False', 'title': 'Back 2 the Future'}
{'favorite': 'False', 'title': 'X-Men'}
{'favorite': 'True', 'title': 'Batman Returns'}
{'favorite': 'False', 'title': 'Reservoir Dogs'}
{'favorite': 'False', 'title': 'ALIEN'}
{'favorite': 'True', 'title': "Ferris Bueller's Day Off"}
{'favorite': 'FALSE', 'title': 'American Psycho'}
{'favorite': 'False', 'title': 'Batman: The Movie'}
{'favorite': 'True', 'title': 'Easy A'}
{'favorite': 'True', 'title': 'Dinner for SCHMUCKS'}
{'favorite': 'False', 'title': 'Ghostbusters'}
{'favorite': 'True', 'title': 'Robin Hood: Prince of Thieves'}

您已经可以看到如何movies以不同的方式输入。暂时不用担心,稍后您将有机会在本教程中修复其中一个错误。

5. XPath 表达式

多时候元素没有属性,它们只有文本内容。使用属性.text,您可以打印出此内容。

现在,打印出电影的所有描述。

for description in root.iter('description'):
    print(description.text)

输出:

     'Archaeologist and adventurer Indiana Jones 
                is hired by the U.S. government to find the Ark of the 
                Covenant before the Nazis.'
None provided.
Marty McFly
Two mutants come to a private academy for their kind whose resident superhero team must 
               oppose a terrorist organization with similar powers.
NA.
WhAtEvER I Want!!!?!
"""""""""
Funny movie about a funny guy
psychopathic Bateman
What a joke!
Emma Stone = Hester Prynne
Tim (Rudd) is a rising executive
                 who “succeeds” in finding the perfect guest, 
                 IRS employee Barry (Carell), for his boss’ monthly event, 
                 a so-called “dinner for idiots,” which offers certain 
                 advantages to the exec who shows up with the biggest buffoon.
Who ya gonna call?
Robin Hood slaying

打印出 XML 是有帮助的,但 XPath 是一种用于快速轻松地搜索 XML 的查询语言。XPath 代表 XML 路径语言,顾名思义,它使用“类似路径”的语法来识别和导航 XML 文档中的节点。


了解 XPath 对于扫描和填充 XML 至关重要。ElementTree有一个.findall()函数将遍历被引用元素的直接子元素。您可以使用 XPath 表达式来指定更有用的搜索。

在这里,您将在树中搜索 1992 年上映的电影:

for movie in root.findall("./genre/decade/movie/[year='1992']"):
    print(movie.attrib)

输出:

{'favorite': 'True', 'title': 'Batman Returns'}
{'favorite': 'False', 'title': 'Reservoir Dogs'}

该函数.findall()总是从指定的元素开始。这种类型的功能对于“查找和替换”来说非常强大。您甚至可以搜索属性!

现在,仅打印以多种格式(属性)可用的电影。

for movie in root.findall("./genre/decade/movie/format/[@multiple='Yes']"):
    print(movie.attrib)

输出:

{'multiple': 'Yes'}
{'multiple': 'Yes'}
{'multiple': 'Yes'}
{'multiple': 'Yes'}
{'multiple': 'Yes'}

集思广益,为什么在这种情况下 print 语句会返回multiple. 想想“for”循环是如何定义的。你能改写这个循环来打印出电影标题吗?在下面试试:

提示:使用’…'inside XPath 返回当前元素的父元素。

for movie in root.findall("./genre/decade/movie/format[@multiple='Yes']..."):
    print(movie.attrib)

输出:

{'favorite': 'True', 'title': 'THE KARATE KID'}
{'favorite': 'False', 'title': 'X-Men'}
{'favorite': 'False', 'title': 'ALIEN'}
{'favorite': 'False', 'title': 'Batman: The Movie'}
{'favorite': 'True', 'title': 'Dinner for SCHMUCKS'}
目录
打赏
0
1
0
0
47
分享
相关文章
深入解析:使用 Python 爬虫获取淘宝店铺所有商品接口
本文介绍如何使用Python结合淘宝开放平台API获取指定店铺所有商品数据。首先需注册淘宝开放平台账号、创建应用并获取API密钥,申请接口权限。接着,通过构建请求、生成签名、调用接口(如`taobao.items.search`和`taobao.item.get`)及处理响应,实现数据抓取。代码示例展示了分页处理和错误处理方法,并强调了调用频率限制、数据安全等注意事项。此技能对开发者和数据分析师极具价值。
Python入门:6.深入解析Python中的序列
在 Python 中,**序列**是一种有序的数据结构,广泛应用于数据存储、操作和处理。序列的一个显著特点是支持通过**索引**访问数据。常见的序列类型包括字符串(`str`)、列表(`list`)和元组(`tuple`)。这些序列各有特点,既可以存储简单的字符,也可以存储复杂的对象。 为了帮助初学者掌握 Python 中的序列操作,本文将围绕**字符串**、**列表**和**元组**这三种序列类型,详细介绍其定义、常用方法和具体示例。
Python入门:6.深入解析Python中的序列
Python入门:2.注释与变量的全面解析
在学习Python编程的过程中,注释和变量是必须掌握的两个基础概念。注释帮助我们理解代码的意图,而变量则是用于存储和操作数据的核心工具。熟练掌握这两者,不仅能提高代码的可读性和维护性,还能为后续学习复杂编程概念打下坚实的基础。
Python入门:2.注释与变量的全面解析
[oeasy]python070_如何导入模块_导入模块的作用_hello_dunder_双下划线
本文介绍了如何在Python中导入模块及其作用,重点讲解了`__hello__`模块的导入与使用。通过`import`命令可以将外部模块引入当前环境,增强代码功能。例如,导入`__hello__`模块后可输出“Hello world!”。此外,还演示了如何使用`help()`和`dir()`函数查询模块信息,并展示了导入多个模块的方法。最后,通过一个实例,介绍了如何利用`jieba`、`WordCloud`和`matplotlib`模块生成词云图。总结来说,模块是封装好的功能部件,能够简化编程任务并提高效率。未来将探讨如何创建自定义模块。
38 8
[oeasy]python071_我可以自己做一个模块吗_自定义模块_引入模块_import_diy
本文介绍了 Python 中模块的导入与自定义模块的创建。首先,我们回忆了模块的概念,即封装好功能的部件,并通过导入 `__hello__` 模块实现了输出 &quot;hello world!&quot; 的功能。接着,尝试创建并编辑自己的模块 `my_file.py`,引入 `time` 模块以获取当前时间,并在其中添加自定义输出。
25 4
通义灵码AI程序员实战:从零构建Python记账本应用的开发全解析
本文通过开发Python记账本应用的真实案例,展示通义灵码AI程序员2.0的代码生成能力。从需求分析到功能实现、界面升级及测试覆盖,AI程序员展现了需求转化、技术选型、测试驱动和代码可维护性等核心价值。文中详细解析了如何使用Python标准库和tkinter库实现命令行及图形化界面,并生成单元测试用例,确保应用的稳定性和可维护性。尽管AI工具显著提升开发效率,但用户仍需具备编程基础以进行调试和优化。
269 9
基于Python的情感分析与情绪识别技术深度解析
本文探讨了基于Python的情感分析与情绪识别技术,涵盖基础概念、实现方法及工业应用。文中区分了情感分析与情绪识别的核心差异,阐述了从词典法到深度学习的技术演进,并通过具体代码展示了Transformers架构在细粒度情感分析中的应用,以及多模态情绪识别框架的设计。此外,还介绍了电商评论分析系统的构建与优化策略,包括领域自适应训练和集成学习等方法。未来,随着深度学习和多模态数据的发展,该技术将更加智能与精准。
47 0
内网桌面监控软件深度解析:基于 Python 实现的 K-Means 算法研究
内网桌面监控软件通过实时监测员工操作,保障企业信息安全并提升效率。本文深入探讨K-Means聚类算法在该软件中的应用,解析其原理与实现。K-Means通过迭代更新簇中心,将数据划分为K个簇类,适用于行为分析、异常检测、资源优化及安全威胁识别等场景。文中提供了Python代码示例,展示如何实现K-Means算法,并模拟内网监控数据进行聚类分析。
52 10
控制局域网上网软件之 Python 字典树算法解析
控制局域网上网软件在现代网络管理中至关重要,用于控制设备的上网行为和访问权限。本文聚焦于字典树(Trie Tree)算法的应用,详细阐述其原理、优势及实现。通过字典树,软件能高效进行关键词匹配和过滤,提升系统性能。文中还提供了Python代码示例,展示了字典树在网址过滤和关键词屏蔽中的具体应用,为局域网的安全和管理提供有力支持。
65 17
Python爬取某云热歌榜:解析动态加载的歌曲数据
Python爬取某云热歌榜:解析动态加载的歌曲数据