【第九节】python中xml解析和json编解码

目录

一、Python XML 解析

1.1 什么是XML

1.2 Python 对 XML 的解析方法

1.3 SAX解析xml

1.4 xml.dom解析xml

1.6 ElementTree解析XML

二、Python编解码json

2.1 什么是json

2.2 使用json 库

2.3 使用第三方库Demjson


一、Python XML 解析

1.1 什么是XML

        XML,全称为可扩展标记语言(eXtensible Markup Language),是一种用于描述数据的标记语言。XML的设计宗旨是传输和存储数据,强调数据的内容和结构,而非数据的显示方式。

以下是XML的一些关键特点:

1). **自描述性**:XML使用标签来定义数据的结构和意义,这些标签可以由用户根据需要自行定义,因此具有很高的灵活性和扩展性。

2). **平台无关性**:XML的文本格式使其独立于具体的硬件和软件平台,可以在不同的系统之间轻松交换数据。

3). **结构化数据**:XML文档通常遵循一定的层次结构,这使得数据更加有序和易于管理。

4). **元标记语言**:XML是一种元标记语言,这意味着它可以用来创建其他特定领域的标记语言。例如,SVG(可缩放矢量图形)和MathML(数学标记语言)都是基于XML的。

5). **可扩展性**:由于XML的标签是自定义的,因此可以根据需要添加新的标签,而不会影响现有的数据和应用程序。

6). **验证机制**:XML可以通过文档类型定义(DTD)或XML Schema来定义数据的结构和约束,从而确保数据的完整性和有效性。

        XML在许多领域都有广泛的应用,包括Web服务、配置文件、数据存储和交换等。它的灵活性和强大的数据描述能力使其成为一种重要的数据处理工具。

1.2 Python 对 XML 的解析方法

        在Python中,解析XML文件主要有三种方法:SAX(Simple API for XML)、DOM(Document Object Model)以及ElementTree。每种方法都有其独特的特点和适用场景。

1. **SAX(Simple API for XML)**:
   - SAX是一种基于事件驱动的解析方式。
   - 在解析XML时,SAX会逐行读取文件,并在识别出特定元素时触发相应的事件。
   - 这种方法不需要将整个XML文档加载到内存中,因此适用于处理大型XML文件。
   - 由于SAX是只读的,它不支持对XML文档的修改。

2. **DOM(Document Object Model)**:
   - DOM解析器会将整个XML文档加载到内存中,并构建一个树状结构的对象模型。
   - 这使得用户可以随机访问树中的任何节点,进行查询、修改、删除或添加操作。
   - 然而,DOM方法在处理大型XML文件时可能会消耗大量内存。

3. **ElementTree**:
   - ElementTree提供了一种轻量级、高效且易于使用的方式来解析和处理XML。
   - 它将XML数据表示为一个树状结构,类似于DOM,但更加简洁和高效。
   - ElementTree支持对XML文档的读取和写入操作,适用于中等大小的XML文件。

        选择哪种解析方法取决于具体需求,例如文件大小、内存限制、是否需要修改XML内容等因素。对于大型文件,SAX可能是更合适的选择;而对于需要频繁修改的中小型文件,ElementTree或DOM可能更为适宜。

1.3 SAX解析xml

        Python中使用SAX解析XML文档时,涉及到两个核心组件:解析器和事件处理器。

        SAX解析器负责逐行读取XML文档,并在识别出特定元素时向事件处理器发送相应的事件,例如元素的开始和结束。

        事件处理器则负责响应这些事件,对传递过来的XML数据进行处理。

SAX解析方式特别适用于以下场景:
1). 处理大型XML文件;
2). 仅需获取文件的部分内容或特定信息;
3). 需要构建自定义对象模型的情况。

        在Python中,使用SAX解析XML需要先导入`xml.sax`模块中的`parse`函数,以及`xml.sax.handler`模块中的`ContentHandler`类。

`ContentHandler`类包含多个方法,用于处理不同类型的XML事件:

- `characters(content)`方法:在遇到字符数据时被调用,`content`参数包含这些字符串。
- `startDocument()`方法:在文档开始时被调用。
- `endDocument()`方法:在文档结束时被调用。
- `startElement(name, attrs)`方法:在遇到XML开始标签时被调用,`name`是标签名,`attrs`是属性值的字典。
- `endElement(name)`方法:在遇到XML结束标签时被调用。

此外,`xml.sax`模块还提供了以下方法:

- `make_parser()`方法:创建并返回一个新的解析器对象。
- `parse(xmlfile, contenthandler[, errorhandler])`方法:创建一个SAX解析器并解析指定的XML文件。
- `parseString(xmlstring, contenthandler[, errorhandler])`方法:创建一个XML解析器并解析指定的XML字符串。

        这些方法和类构成了Python中使用SAX解析XML的基础框架,开发者可以根据具体需求重写`ContentHandler`类中的方法,以实现对XML数据的定制化处理。

我们实验使用到的 XML 实例文件 movies.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>

解析上面xml的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")

代码执行结果如下:

*****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

1.4 xml.dom解析xml

        文件对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展置标语言的标准编程接口。

        一个 DOM 的解析器在解析一个 XML 文档时,一次性读取整个文档,把文档中所有元素保存在内存中的一个树结构里,之后你可以利用DOM 提供的不同的函数来读取或修改文档的内容和结构,也可以把修改过的内容写入xml文件。

python中用xml.dom.minidom来解析xml文件,实例如下:

#!/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

执行结果如下:

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

1.6 ElementTree解析XML

import xml.etree.ElementTree as ET

# 解析XML文件
tree = ET.parse('movies.xml')
root = tree.getroot()

# 遍历所有的movie元素
for movie in root.findall('movie'):
    # 获取movie的属性
    title = movie.get('title')
    # 获取子元素的文本内容
    movie_type = movie.find('type').text
    format = movie.find('format').text
    year = movie.find('year').text if movie.find('year') is not None else 'N/A'
    rating = movie.find('rating').text
    stars = movie.find('stars').text
    description = movie.find('description').text
    
    # 打印信息
    print(f"Title: {title}")
    print(f"Type: {movie_type}")
    print(f"Format: {format}")
    print(f"Year: {year}")
    print(f"Rating: {rating}")
    print(f"Stars: {stars}")
    print(f"Description: {description}")
    print("-" * 40)

二、Python编解码json

2.1 什么是json

        JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。JSON 是基于 JavaScript 编程语言的一个子集,但它是独立于语言的文本格式,因此可以在多种编程语言中使用。

### JSON 的结构

JSON 数据格式主要由两种结构组成:

1). **键值对集合**:这通常表现为对象(object),在 JSON 中用花括号 `{}` 表示。每个键值对由一个键和一个值组成,键和值之间用冒号 `:` 分隔,每个键值对之间用逗号 `,` 分隔。例如:
   ```json
   {
     "name": "John",
     "age": 30,
     "city": "New York"
   }
   ```

2). **值的有序列表**:这通常表现为数组(array),在 JSON 中用方括号 `[]` 表示。数组中的每个值之间用逗号 `,` 分隔。例如:
   ```json
   [
     "apple",
     "banana",
     "cherry"
   ]
   ```

JSON 支持以下数据类型:
- 字符串(string)
- 数字(number)
- 对象(object)
- 数组(array)
- 布尔值(boolean)
- null

### JSON 的应用

        JSON 由于其简洁性和通用性,在现代软件开发中得到了广泛的应用,主要包括以下几个方面:

1). **数据交换**:JSON 常用于不同系统之间的数据交换,特别是在 Web 开发中,前端和后端之间通过 JSON 格式传递数据。

2). **配置文件**:JSON 格式简洁易读,常被用作配置文件的格式,如应用程序的设置文件。

3). **API 响应**:RESTful API 通常使用 JSON 格式返回数据,使得客户端能够轻松解析和处理。

4). **日志记录**:JSON 格式的日志易于解析和查询,因此在日志记录系统中也得到了广泛应用。

5). **存储数据**:虽然 JSON 不是数据库格式,但在某些情况下,它被用于存储结构化数据,尤其是在需要快速读写的场景中。

6). **移动应用**:移动应用开发中,JSON 常用于从服务器获取数据,并在应用中进行展示和处理。

7). **物联网(IoT)**:在物联网设备中,JSON 常用于设备与服务器之间的数据传输。

JSON 的广泛应用得益于其简单、灵活和易于处理的特性,使得它成为现代软件开发中不可或缺的一部分。

2.2 使用json 库

        在Python中,处理JSON对象非常简单,因为Python标准库提供了`json`模块,用于编码(序列化)和解码(反序列化)JSON数据。以下是如何使用`json`模块进行JSON编码和解码的示例:

### 编码(序列化)JSON对象

        要将Python对象编码为JSON字符串,可以使用`json.dumps()`方法。以下是一个示例:

import json

# 定义一个Python对象
data = {
    "name": "John Doe",
    "age": 30,
    "city": "New York",
    "is_student": False,
    "courses": ["Math", "Science", "History"]
}

# 将Python对象编码为JSON字符串
json_string = json.dumps(data, indent=4)
print(json_string)

        在这个示例中,我们定义了一个Python字典`data`,然后使用`json.dumps()`方法将其编码为JSON字符串。`indent=4`参数用于美化输出,使JSON字符串更易读。

  python 原始类型向 json 类型的转化对照表:

### 解码(反序列化)JSON对象

        要将JSON字符串解码为Python对象,可以使用`json.loads()`方法。以下是一个示例:

import json

# 定义一个JSON字符串
json_string = '''
{
    "name": "John Doe",
    "age": 30,
    "city": "New York",
    "is_student": false,
    "courses": ["Math", "Science", "History"]
}'''

# 将JSON字符串解码为Python对象
data = json.loads(json_string)
print(data)
print(type(data))  # 输出: <class 'dict'>

        在这个示例中,我们定义了一个JSON字符串`json_string`,然后使用`json.loads()`方法将其解码为Python字典。

json 类型转换到 python 的类型对照表:

### 处理文件中的JSON数据

        如果需要从文件中读取JSON数据或将JSON数据写入文件,可以使用`json.load()`和`json.dump()`方法。以下是一个示例:

import json

# 写入JSON数据到文件
data = {
    "name": "John Doe",
    "age": 30,
    "city": "New York",
    "is_student": False,
    "courses": ["Math", "Science", "History"]
}

with open('data.json', 'w') as file:
    json.dump(data, file, indent=4)

# 从文件中读取JSON数据
with open('data.json', 'r') as file:
    data = json.load(file)
    print(data)

        在这个示例中,我们首先使用`json.dump()`方法将Python对象`data`写入名为`data.json`的文件中。然后,使用`json.load()`方法从文件中读取JSON数据并将其解码为Python对象。

        通过这些方法,你可以轻松地在Python中处理JSON数据。

2.3 使用第三方库Demjson

        `demjson` 是一个第三方 Python 模块,提供了对 JSON 数据的编码和解码功能,并且包含了 JSONLint 的格式化及校验功能。以下是如何使用 `demjson` 模块进行 JSON 编码和解码的详细步骤和示例。

### 安装 `demjson`

        首先,你需要安装 `demjson` 模块。你可以从源码安装,也可以使用 `pip` 安装。以下是从源码安装的步骤:

$ tar -xvzf demjson-2.2.3.tar.gz
$ cd demjson-2.2.3
$ python setup.py install

或者使用 `pip` 安装:

$ pip install demjson

### 编码 JSON 数据

`demjson` 的 `encode` 函数用于将 Python 对象编码成 JSON 字符串。

#### 语法

demjson.encode(self, obj, nest_level=0)

#### 示例

以下是一个将 Python 列表编码为 JSON 字符串的示例:

#!/usr/bin/python
import demjson

data = [ { 'a' : 1, 'b' : 2, 'c' : 3, 'd' : 4, 'e' : 5 } ]

json_string = demjson.encode(data)
print(json_string)

输出结果为:

[{"a":1,"b":2,"c":3,"d":4,"e":5}]

### 解码 JSON 数据

`demjson` 的 `decode` 函数用于将 JSON 字符串解码为 Python 对象。

#### 语法

demjson.decode(self, txt)

#### 示例

以下是一个将 JSON 字符串解码为 Python 字典的示例:

#!/usr/bin/python
import demjson

json_string = '{"a":1,"b":2,"c":3,"d":4,"e":5}';

data = demjson.decode(json_string)
print(data)

输出结果为:

{u'a': 1, u'c': 3, u'b': 2, u'e': 5, u'd': 4}

### 总结

        `demjson` 模块提供了简单易用的方法来处理 JSON 数据。通过 `encode` 和 `decode` 函数,你可以轻松地在 Python 对象和 JSON 字符串之间进行转换。如果你需要更高级的 JSON 处理功能,`demjson` 可能是一个不错的选择。

  • 13
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

攻城狮7号

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值