XML作为一种最常见的通用标准格式,其被用于各种不同场合,如web服务、数据存储和数据交换。因此,深入掌握 XML 的解析技术对于软件开发人员来说至关重要。本文将从XML的概念入手,逐步介绍如何解析XML,并演示解析XML的技巧和流程,希望能帮助读者成为XML解析高手。
一、XML简介
XML(Extensible Markup Language)是一种标记语言,它设计用于传输和存储数据。与HTML不同,XML具有自定义的标签和属性,可以随意扩展。XML的语法超过了HTML,它支持多种数据类型,包括文本、数字、日期等等,而且可以表现出复杂的结构。例如:
```
John Doe
30
Male
```
解析XML是将XML数据转换为其他结构,例如对象、数组、文档等等。解析XML可以通过DOM、SAX、StAX等多种方式实现。下面,我们将逐一介绍这些方法。
二、DOM 解析器
DOM是针对XML文档而设计的编程接口,其将XML文档读入内存,并形成一棵树形结构,最后提供一种可以遍历这棵树的方法。
在DOM中,每一个XML元素都是一个节点。节点包含许多属性,例如节点的类型(元素、属性、文本),节点的名称,以及节点的一组子节点。
DOM解析器是最简单的XML解析器,它可以将XML文档解析成DOM树。DOM解析器允许用户通过DOM API遍历树的节点,并获取节点的数据。例如:
```python
import xml.dom.minidom
# 使用minidom解析器打开 XML 文档
DOMTree = xml.dom.minidom.parse("example.xml")
collection = DOMTree.documentElement
# 获取所有 book
books = collection.getElementsByTagName("book")
# 处理每一个 book 节点
for book in books:
print("==============================")
if book.hasAttribute("id"):
print("ID: {0}".format(book.getAttribute("id")))
# 获取name节点
name = book.getElementsByTagName('name')[0]
print("Name: {0}".format(name.childNodes[0].data))
# 获取author节点
author = book.getElementsByTagName('author')[0]
print("Author: {0}".format(author.childNodes[0].data))
# 获取price节点
price = book.getElementsByTagName('price')[0]
print("Price: {0}".format(price.childNodes[0].data))
```
在上述代码中,我们首先使用minidom解析器打开XML文档,然后获取所有的book节点,并逐一遍历并处理每个book节点,最后获取其中的子节点信息。
虽然DOM解析器易于使用,但它具有对整棵树的一个完整拷贝,因此对于大型XML文档而言,它可能会消耗大量的内存。
三、SAX 解析器
SAX(Simple API for XML)是另一种解析XML文档的方法,与DOM解析器不同的是,SAX解析器并不将整个XML文档解析到内存中,而是一边读取一遍解析。因此,SAX解析器比DOM解析器更为高效,特别在处理大型XML文档时更显著。SAX解析器需要一个事件驱动执行程序,以便“先读通道”的方法来处理XML文档的内容及结构。
在SAX中,当解析器遇到XML标记时,它会发出事件通知应用程序,例如:
```python
import xml.sax
class BookHandler(xml.sax.ContentHandler):
def __init__(self):
self.CurrentData = ""
self.name = ""
self.author = ""
self.price = ""
def startElement(self, tag, attributes):
self.CurrentData = tag
if tag == "book":
print("==============================")
if "id" in attributes:
print("ID: {0}".format(attributes["id"]))
def endElement(self, tag):
if self.CurrentData == "name":
print("Name: {0}".format(self.name))
elif self.CurrentData == "author":
print("Author: {0}".format(self.author))
elif self.CurrentData == "price":
print("Price: {0}".format(self.price))
self.CurrentData = ""
def characters(self, content):
if self.CurrentData == "name":
self.name = content
elif self.CurrentData == "author":
self.author = content
elif self.CurrentData == "price":
self.price = content
if ( __name__ == "__main__"):
# 创建一个 XMLReader
parser = xml.sax.make_parser()
# 禁用命名空间
parser.setFeature(xml.sax.handler.feature_namespaces, 0)
# 重写 ContextHandler
Handler = BookHandler()
parser.setContentHandler( Handler )
parser.parse("example.xml")
```
在上述代码中,我们首先创建一个BookHandler类,以重写sax.ContentHandler类的startElement、endElement和characters方法。然后,我们创建一个解析器对象,并使用BookHandler类处理该 XML文档。
可以看出,SAX解析器适合处理大型XML文档,但是它不能随机访问XML元素;因此,很难实现XML文档的修改。
四、StAX 解析器
StAX是解析XML文档的一种流式方法,它可以在读取XML文档时,一行一行地将其解析成对象,这样就可以最小化内存使用。它比SAX解析器更好,尤其在需要解析多个XML数据或处理大型XML文档时。与DOM解析器不同的是,StAX解析器不需要模拟完整的XML文档树,因此,它可以在过程中修改XML文档。StAX有两种方式:基于事件和基于游标。
基于事件:
```python
import xml.etree.ElementTree as ET
import xml.etree.ElementTree as etree
from xml.etree.ElementTree import iterparse
for event, elem in iterparse('example.xml', events=('start', 'end')):
if event == 'start':
print(f'Start Element: {elem.tag} {elem.attrib}')
if event == 'end':
print(f'End Element: {elem.tag}')
```
基于游标:
基于游标的StAX解析器使用游标进行寻址,其不能像DOM一样编辑XML元素,但是基于游标的StAX解析器比基于事件的StAX解析器更快,尤其是在处理大型XML文件时。
```python
import xml.etree.ElementTree as ET
def log_node(node, tabs):
print(f'{tabs}node : tag={node.tag} attrs={node.attrib}')
for n in node:
log_node(n, tabs+'\t')
def main():
tree = ET.iterparse('example.xml')
for event, elem in tree:
if elem.tag == 'book':
log_node(elem, '\t')
elem.clear()
if __name__ == '__main__':
main()
```
在上述代码中,我们使用iterparse来解析XML文件,读取文件时生成ET.Element树,并使用log_node()函数打印节点和属性,实现基于游标的XML解析。
总结:
本文介绍了XML的概述和解析方法(DOM,SAX和StAX)。DOM解析器受内存限制,适用于较小的文档,但可以方便地修改XML。相反,SAX编排器可能更慢,但适用于大型文档,并具有更好的内存管理,但不能修改XML。 StAX解析器可以使用内存管理通过XML,也可以修改XML。
阅读本文后,您应该对解析XML文件有了更深入的了解。我们建议您根据您的XML文件特征来选择某种特定的解析器,以获得最好的性能。祝您成为XML解析高手!