天天看點

python xml 解析_Python-解析 XML

簡介

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: 女