簡介
XML 全稱 Extensible Markup Language,中文譯為可擴充标記語言。
XML 之前有兩個先行者:SGML 和 HTML,率先登場的是 SGML, 盡管它功能強大,但文檔結構複雜,既不容易學也不易于使用,是以幾個主要的浏覽器廠商均拒絕支援 SGML,這些因素限制了 SGML 在網上的傳播性;1989 年 HTML 登場,它繼承了 SGML 諸多優點,去除了 SGML 複雜龐大的缺點,HTML 在資料顯示上表現十分出色,但它的文法是不可擴充的,是以其無法描述資料、可讀性差,沒辦法人們再次将目光轉向 SGML,經過對 SGML 一系列改造,終于在 1998 年,XML 第一個版本問世。
簡單來說就是:XML 和 HTML 均由 SGML 改造而來,HTML 是一種頁面技術,聚焦的是資料的顯示,而 XML 易于擴充,主要用來傳送和存儲資料,聚焦的是資料的内容。
解析
解析方式
Python 有三種 XML 解析方式:SAX(simple API for XML)、DOM(Document Object Model)、ElementTree。
DOM 方式:DOM 中文譯為文檔對象模型,是 W3C 組織推薦的标準程式設計接口,它将 XML 資料在記憶體中解析成一個樹,通過對樹的操作來操作 XML。
SAX 方式:SAX 是一個用于處理 XML 事件驅動的模型,它逐行掃描文檔,一邊掃描一邊解析,對于大型文檔的解析擁有巨大優勢,盡管不是 W3C 标準,但它卻得到了廣泛認可。
ElementTree 方式:ElementTree 相對于 DOM 來說擁有更好的性能,與 SAX 性能差不多,API 使用也很友善。
具體實作
在具體解析之前我們先準備一個 XML,如下所示:
test.xml
<?xml version="1.0" encoding="utf-8"?>
1001
張三
22
男
1002
李四
21
女
DOM 方式解析
使用 DOM 方式,首先要對其 API 有一定了解,如果不了解,網上的教程也比較多,比如:DOM 教程,下面看一下使用示例。
from xml.dom.minidom importparse#讀取檔案
dom = parse('test.xml')#擷取文檔元素對象
data =dom.documentElement#擷取 student
stus = data.getElementsByTagName('student')for stu instus:#擷取标簽屬性值
st_id = stu.getAttribute('id')
st_name= stu.getAttribute('name')#擷取标簽中内容
id = stu.getElementsByTagName('id')[0].childNodes[0].nodeValue
name= stu.getElementsByTagName('name')[0].childNodes[0].nodeValue
age= stu.getElementsByTagName('age')[0].childNodes[0].nodeValue
gender= stu.getElementsByTagName('gender')[0].childNodes[0].nodeValueprint('st_id:', st_id, ', st_name:',st_name)print('id:', id, ', name:', name, ', age:', age, ', gender:',gender)
輸出結果:
st_id: stu1 , st_name: stu
id:1001 , name: 張三 , age: 22, gender: 男
st_id: stu2 , st_name: stu
id:1002 , name: 李四 , age: 21 , gender: 女
通過輸出結果,我們可以發現已經擷取了标簽屬性值和标簽内容了。
SAX 方式解析
使用 SAX 解析 XML 文檔主要涉及到解析器和事件處理器,解析器負責讀取 XML 文檔,并向事件處理器發送事件,事件處理器負責對事件作出響應,對傳遞的 XML 資料進行處理。
Python 使用 SAX 處理 XML 需要用到 xml.sax 中的 parse 函數和 xml.sax.handler 中的 ContentHandler 類,下面看一下 ContentHandler 類中的一些方法。
characters(content):調用時機:從行開始,遇到标簽之前,存在字元,content 的值為這些字元串;從一個标簽,遇到下一個标簽之前, 存在字元,content 的值為這些字元串;從一個标簽,遇到行結束符之前,存在字元,content 的值為這些字元串。
startDocument():文檔啟動的時候調用。
endDocument():解析器到達文檔結尾時調用。
startElement(name, attrs):遇到 XML 開始标簽時調用,name 是标簽的名字,attrs 是标簽的屬性值字典。
endElement(name):遇到 XML 結束标簽時調用。
下面通過示例看一下如何通過 SAX 方式解析 XML。
importxml.saxclassStudentHandler(xml.sax.ContentHandler):def __init__(self):
self.id= ""self.name= ""self.age= ""self.gender= ""
#元素開始調用
defstartElement(self, tag, attributes):
self.CurrentData=tagif tag == "student":
stu_name= attributes["name"]print("stu_name:", stu_name)#元素結束調用
defendElement(self, tag):if self.CurrentData == "id":print("id:", self.id)elif self.CurrentData == "name":print("name:", self.name)elif self.CurrentData == "age":print("age:", self.age)elif self.CurrentData == "gender":print("gender:", self.gender)
self.CurrentData= ""
#讀取字元時調用
defcharacters(self, content):if self.CurrentData == "id":
self.id=contentelif self.CurrentData == "name":
self.name=contentelif self.CurrentData == "age":
self.age=contentelif self.CurrentData == "gender":
self.gender=contentif (__name__ == "__main__"):#建立 XMLReader
parser =xml.sax.make_parser()#關閉命名空間
parser.setFeature(xml.sax.handler.feature_namespaces, 0)#重寫 ContextHandler
Handler =StudentHandler()
parser.setContentHandler(Handler)
parser.parse("test.xml")
輸出結果:
stu_name: stu
id:1001name: 張三
age:22gender: 男
stu_name: stu
id:1002name: 李四
age:21gender: 女
ElementTree 方式解析
Python 提供了兩種 ElementTree 的實作方式。一個是純 Python 實作的 xml.etree.ElementTree,另一個是 C 語言實作 xml.etree.cElementTree,使用 C 語言實作的方式速度更快且記憶體消耗更少。Python3.3 之後,ElemenTree 子產品會自動優先使用 C 加速器,如果不存在 C 實作,則會使用 Python 實作。是以,使用 Python3.3+ 時,隻需要 import xml.etree.ElementTree 即可。下面看一下示例。
importxml.etree.ElementTree as ET
tree= ET.parse("test.xml")#根節點
root =tree.getroot()#标簽名
print('root_tag:',root.tag)for stu inroot:#屬性值
print ("stu_name:", stu.attrib["name"])#标簽中内容
print ("id:", stu[0].text)print ("name:", stu[1].text)print("age:", stu[2].text)print("gender:", stu[3].text)
輸出結果:
root_tag: list
stu_name: stu
id:1001name: 張三
age:22gender: 男
stu_name: stu
id:1002name: 李四
age:21gender: 女