【Python】解析 XML

1、Python 对 XML 的解析

1.1 SAX (simple API for XML )

SAX 解析器使用事件驱动模型,通过在解析XML的过程中触发一个个的事件并调用用户定义的回调函数来处理XML文件。

xml.sax 模块牺牲了便捷性来换取速度和内存占用。

事件驱动指一种基于回调(callback)机制的程序运行方法。

利用SAX解析XML文档牵涉到两个部分:

  • 解析器:负责读取XML文档,并向事件处理器发送事件,如元素开始跟元素结束事件。
  • 事件处理器:负责对事件作出响应,对传递的XML数据进行处理。

SAX适用场景:

  • 对大型文件进行处理;
  • 只需要文件的部分内容,或者只需从文件中得到特定信息。
  • 想建立自己的对象模型的时候。

1.2 DOM(Document Object Model)

DOM 解析器在任何处理开始之前,必须把基于XML文件生成的树状数据放在内存,所以DOM解析器的内存使用量完全根据输入资料的大小。

  • xml.dom.minidom
    minidom 是DOM API的极简化实现,比完整版的DOM要简单的多,而且这个包也小的多。
  • xml.dom.pulldom
    pulldom模块提供的是一个"pull解析器",其背后的基本概念指的是从XML流中pull事件,然后进行处理。虽然与SAX一样采用事件驱动模型(event-driven processing model),但是不同的是,使用pull解析器时,使用者需要明确地从XML流中pull事件,并对这些事件遍历处理,直到处理完成或者出现错误。

1.3 ElementTree(元素树)

xml.etree.ElementTree 模块提供了一个轻量级、Pythonic的API,同时还有一个高效的C语言实现,即 xml.etree.cElementTree

与 DOM 相比,ET的速度更快,API使用更直接、方便。

与 SAX 相比,ET.iterparse 函数同样提供了按需解析的功能,不会一次性在内存中读入整个文档。ET的性能与SAX模块大致相仿,但是它的API更加高层次,用户使用起来更加便捷。

1.4 xml.parser.expat

xml.parser.expat 提供了对C语言编写的expat解析器的一个直接的、底层API接口。expat接口与SAX类似,也是基于事件回调机制,但是这个接口并不是标准化的,只适用于expat库。

expat是一个面向流的解析器。您注册的解析器回调(或handler)功能,然后开始搜索它的文档。当解析器识别该文件的指定的位置,它会调用该部分相应的处理程序(如果您已经注册的一个)。该文件被输送到解析器,会被分割成多个片断,并分段装到内存中。因此expat可以解析那些巨大的文件。

1.5 lxml

lxml 是一个第三方库,它提供了更强大的XML处理功能,包括XPath支持、XML Schema验证、HTML支持等。

1.6 xmltodict

xmltodict是一个第三方库,它提供了一个功能,将Python的字典对象转换为XML,反之亦然。

2、示例

XML 实例文件 movies.xml 内容如下:

xml 复制代码
<collection shelf="New Arrivals">
<movie title="Enemy Behind">
   <type>War, Thriller</type>
   <format>DVD</format>
   <year>2003</year>
   <rating>PG</rating>
   <stars>10</stars>
   <description>Talk about a US-Japan war</description>
</movie>
<movie title="Transformers">
   <type>Anime, Science Fiction</type>
   <format>DVD</format>
   <year>1989</year>
   <rating>R</rating>
   <stars>8</stars>
   <description>A schientific fiction</description>
</movie>
   <movie title="Trigun">
   <type>Anime, Action</type>
   <format>DVD</format>
   <episodes>4</episodes>
   <rating>PG</rating>
   <stars>10</stars>
   <description>Vash the Stampede!</description>
</movie>
<movie title="Ishtar">
   <type>Comedy</type>
   <format>VHS</format>
   <rating>PG</rating>
   <stars>2</stars>
   <description>Viewable boredom</description>
</movie>
</collection>

2.1 xml.sax

python 复制代码
#!/usr/bin/python
# -*- coding: UTF-8 -*-
 
import xml.sax
 
class MovieHandler( xml.sax.ContentHandler ):
   def __init__(self):
      self.CurrentData = ""
      self.type = ""
      self.format = ""
      self.year = ""
      self.rating = ""
      self.stars = ""
      self.description = ""
 
   # 元素开始事件处理
   def startElement(self, tag, attributes):
      self.CurrentData = tag
      if tag == "movie":
         print "*****Movie*****"
         title = attributes["title"]
         print "Title:", title
 
   # 元素结束事件处理
   def endElement(self, tag):
      if self.CurrentData == "type":
         print "Type:", self.type
      elif self.CurrentData == "format":
         print "Format:", self.format
      elif self.CurrentData == "year":
         print "Year:", self.year
      elif self.CurrentData == "rating":
         print "Rating:", self.rating
      elif self.CurrentData == "stars":
         print "Stars:", self.stars
      elif self.CurrentData == "description":
         print "Description:", self.description
      self.CurrentData = ""
 
   # 内容事件处理
   def characters(self, content):
      if self.CurrentData == "type":
         self.type = content
      elif self.CurrentData == "format":
         self.format = content
      elif self.CurrentData == "year":
         self.year = content
      elif self.CurrentData == "rating":
         self.rating = content
      elif self.CurrentData == "stars":
         self.stars = content
      elif self.CurrentData == "description":
         self.description = content
  
if ( __name__ == "__main__"):
   
   # 创建一个 XMLReader
   parser = xml.sax.make_parser()
   # turn off namepsaces
   parser.setFeature(xml.sax.handler.feature_namespaces, 0)
 
   # 重写 ContextHandler
   Handler = MovieHandler()
   parser.setContentHandler( Handler )
   
   parser.parse("movies.xml")

运行结果:

powershell 复制代码
*****Movie*****
Title: Enemy Behind
Type: War, Thriller
Format: DVD
Year: 2003
Rating: PG
Stars: 10
Description: Talk about a US-Japan war
*****Movie*****
Title: Transformers
Type: Anime, Science Fiction
Format: DVD
Year: 1989
Rating: R
Stars: 8
Description: A schientific fiction
*****Movie*****
Title: Trigun
Type: Anime, Action
Format: DVD
Rating: PG
Stars: 10
Description: Vash the Stampede!
*****Movie*****
Title: Ishtar
Type: Comedy
Format: VHS
Rating: PG
Stars: 2
Description: Viewable boredom

2.2 xml.dom

python 复制代码
#!/usr/bin/python
# -*- coding: UTF-8 -*-
 
from xml.dom.minidom import parse
import xml.dom.minidom
 
# 使用minidom解析器打开 XML 文档
DOMTree = xml.dom.minidom.parse("movies.xml")
collection = DOMTree.documentElement
if collection.hasAttribute("shelf"):
   print "Root element : %s" % collection.getAttribute("shelf")
 
# 在集合中获取所有电影
movies = collection.getElementsByTagName("movie")
 
# 打印每部电影的详细信息
for movie in movies:
   print "*****Movie*****"
   if movie.hasAttribute("title"):
      print "Title: %s" % movie.getAttribute("title")
 
   type = movie.getElementsByTagName('type')[0]
   print "Type: %s" % type.childNodes[0].data
   format = movie.getElementsByTagName('format')[0]
   print "Format: %s" % format.childNodes[0].data
   rating = movie.getElementsByTagName('rating')[0]
   print "Rating: %s" % rating.childNodes[0].data
   description = movie.getElementsByTagName('description')[0]
   print "Description: %s" % description.childNodes[0].data

运行结果:

powershell 复制代码
Root element : New Arrivals
*****Movie*****
Title: Enemy Behind
Type: War, Thriller
Format: DVD
Rating: PG
Description: Talk about a US-Japan war
*****Movie*****
Title: Transformers
Type: Anime, Science Fiction
Format: DVD
Rating: R
Description: A schientific fiction
*****Movie*****
Title: Trigun
Type: Anime, Action
Format: DVD
Rating: PG
Description: Vash the Stampede!
*****Movie*****
Title: Ishtar
Type: Comedy
Format: VHS
Rating: PG
Description: Viewable boredom

2.3 xml.etree.ElementTree

python 复制代码
import xml.etree.ElementTree as ET

xml_string = '''
        <book id="10086">
            <title lang="en">Good Omens</title>
            <authors>
                <name>Neil Gaiman</name>
                <name>Terry Pratchett</name>
            </authors>
            <year>1990</year>
        </book>
    '''

root = ET.fromstring(xml_string)

# 获取根元素的标签
print(root.tag)

# 获取根元素的文本内容
print(root.text)

# 获取根元素的属性
print(root.attrib)

# 查找第一个title元素
print(root.find("title").text)

# 查找所有author元素
names = root.find("authors").findall("name")
for name in names:
    print(name.text)

# 修改title元素的文本内容
root.find("title").text = "The Nice and Accurate Prophecies of Agnes Nutter, Witch"

# 添加一个新的元素
new_year = ET.SubElement(root, "year")
new_year.text = "2024"

# 将修改后的元素转换为字符串
new_xml_string = ET.tostring(root, encoding="unicode")
print(new_xml_string)

运行结果:

powershell 复制代码
book

            
{'id': '10086'}
Good Omens
Neil Gaiman
Terry Pratchett
<book id="10086">
            <title lang="en">The Nice and Accurate Prophecies of Agnes Nutter, Witch</title>
            <authors>
                <name>Neil Gaiman</name>
                <name>Terry Pratchett</name>
            </authors>
            <year>1990</year>
        <year>2024</year></book>     

10、资料

相关推荐
青 春 记 忆7 小时前
Dify Docker Compose 通用无损升级指南:从备份、双版本预演到切换与回滚
运维·人工智能·python·docker·容器
GlueNa2SiO37 小时前
03-Flask模板引擎Jinja2详解
笔记·python·flask
临沂GEO9 小时前
GEO搜索优化科普|正规地理位置流量运营入门指南
大数据·人工智能·python·流量运营
大模型码小白9 小时前
Spring AI Tool 实现自然语言操作 MySQL 数据库详解
服务器·开发语言·数据库·人工智能·python·mysql·spring
荷蒲11 小时前
【小白量化Qbuddy】利用AI学习中文Python
人工智能·python·学习
数据狐(Datafox)12 小时前
京东商品列表API技术解析与落地应用(含标准 JSON 示例)
java·大数据·前端·人工智能·python·数据分析·json
量化吞吐机12 小时前
2026年下半年手工交易规则走向量化表达,产品该先接住哪一步
人工智能·python
Metaphor69213 小时前
使用 Python 读取和删除 Excel 文件属性
python·excel
迷迭香yy14 小时前
Python构建转融券多空识别系统从接口到因子的全流程 IG50免费开源股票数据API接口
开发语言·python·开源