一、說明
類似json將xml解析為python對象,可以使用第三方庫untangle或xmltodict實現。
將以下內容保存為xml2obj.xml,后我我們就使用該文件。
1.第一行的是xml文件的聲明,它定義了xml的版本 (1.0)和所使用編碼為UTF-8。
2.接下來就是xml文件的內容了,這些內容按一個樹狀結構進行組織擺放,形式如下:
section1 content
section2 content
其中,每一個.叫做一個節點,也叫一個元素,節點可以嵌套放置,也可以并列放置,在嵌套結構中,內外層節點是父子關系,以此類推,最外層的節點都叫做根節點。并列的兩節點為兄弟關系。
3.對于每一個節點,一般由Tag、Attribute、Text三部分構成。在country_data.xml中data,country,rank,year這些都是tag。與tag同一尖括弧內右邊的是Attribute,比如:name。Text就是兩個尖括弧中間夾的東西了。
二、使用untangle將xml文件解析為python對象
pip install untangle
import untangle
#將文件解析成對象
obj = untangle.parse('xml2obj.xml')
#獲取
三、使用xmltodict將xml文件解析為python對象
pip install xmltodict
import xmltodict
#將xml文件解析成對象
with open('xml2obj.xml') as fd:
dict = xmltodict.parse(fd.read())
#獲取
四、xml.etree.ElementTree
ElementTree生來就是為了處理XML,它在Python標準庫中有兩種實現:一種是純Python實現的,如xml.etree.ElementTree,另一種是速度快一點的xml.etree.cElementTree。注意:盡量使用C語言實現的那種,因為它速度更快,而且消耗的內存更少。
在CODE上查看代碼片派生到我的代碼片。
1
2008
141100
4
2011
59900
68
2011
13600
234
2016
346344
try:
import xml.etree.cElementTree as ET
except ImportError:
import xml.etree.ElementTree as ET
import sys
try:
tree = ET.parse("xml2obj.xml") # 打開xml文檔
# root = ET.fromstring(country_string) #從字符串傳遞xml
root = tree.getroot() # 獲得root節點
except: # Exception, e:
print("Error:cannot parse file:xml2obj.xml.")
sys.exit(1)
print(root.tag, "--+-", root.attrib)
for child in root:
print(child.tag, "---", child.attrib)
print("*" * 10)
print(root[0][1].text) # 通過下標訪問 )
print(root[0].tag, root[0].text)
print("*" * 10)
for country in root.findall('country'): # 找到root節點下的所有country節點
rank = country.find('rank').text # 子節點下節點rank的值
name = country.get('name') # 子節點下屬性name的值
print(name, rank)
# 修改xml文件
for country in root.findall('country'):
rank = int(country.find('rank').text)
if rank > 50:
root.remove(country)
tree.write('output.xml')
5、xml.dom.*
文件對象模型(Document Object Model,簡稱DOM),是W3C組織推薦的處理可擴展置標語言的標準編程接口。一個 DOM 的解析器在解析一個XML文檔時,一次性讀取整個文檔
from xml.dom.minidom import parse
import xml.dom.minidom
#使用minidom解析器打開XML文檔
DOMTree = xml.dom.minidom.parse("xml2obj.xml")
Data = DOMTree.documentElement
if Data.hasAttribute("name"):
print("name element : %s" % Data.getAttribute("name"))
#在集合中獲取所有國家
Countrys = Data.getElementsByTagName("country")
#打印每個國家的詳細信息
for Country in Countrys:
print("*****Country*****")
if Country.hasAttribute("name"):
print("name: %s" % Country.getAttribute("name"))
rank = Country.getElementsByTagName('rank')[0]
print("rank: %s" % rank.childNodes[0].data)
year = Country.getElementsByTagName('year')[0]
print("year: %s" % year.childNodes[0].data)
gdppc = Country.getElementsByTagName('gdppc')[0]
print("gdppc: %s" % gdppc.childNodes[0].data)
for neighbor in Country.getElementsByTagName("neighbor"):
print(neighbor.tagName, ":", neighbor.getAttribute("name"), neighbor.getAttribute("direction"))
6、xml.dom.*
SAX是一種基于事件驅動的API,利用SAX解析XML牽涉到兩個部分:解析器和事件處理器。其中解析器負責讀取XML文檔,并向事件處理器發送事件,如元素開始跟元素結束事件;而事件處理器則負責對事件作出相應,對傳遞的XML數據進行處理
ContentHandler類方法介紹
(1)characters(content)方法
調用時機:
從行開始,遇到標簽之前,存在字符,content的值為這些字符串。
從一個標簽,遇到下一個標簽之前, 存在字符,content的值為這些字符串。
從一個標簽,遇到行結束符之前,存在字符,content的值為這些字符串。
標簽可以是開始標簽,也可以是結束標簽。
(2)startDocument()方法
文檔啟動的時候調用。
(3)endDocument()方法
解析器到達文檔結尾時調用。
(4)startElement(name, attrs)方法
遇到XML開始標簽時調用,name是標簽的名字,attrs是標簽的屬性值字典。
(5)endElement(name)方法
遇到XML結束標簽時調用。
在CODE上查看代碼片派生到我的代碼片
import xml.sax
class CountryHandler(xml.sax.ContentHandler):
def __init__(self):
self.CurrentData = ""
self.rank = ""
self.year = ""
self.gdppc = ""
self.neighborname = ""
self.neighbordirection = ""
# 元素開始事件處理
def startElement(self, tag, attributes):
self.CurrentData = tag
if tag == "country":
print "*****Country*****"
name = attributes["name"]
print "name:", name
elif tag == "neighbor":
name = attributes["name"]
direction = attributes["direction"]
print name, "->", direction
# 元素結束事件處理
def endElement(self, tag):
if self.CurrentData == "rank":
print "rank:", self.rank
elif self.CurrentData == "year":
print "year:", self.year
elif self.CurrentData == "gdppc":
print "gdppc:", self.gdppc
self.CurrentData = ""
# 內容事件處理
def characters(self, content):
if self.CurrentData == "rank":
self.rank = content
elif self.CurrentData == "year":
self.year = content
elif self.CurrentData == "gdppc":
self.gdppc = content
if __name__ == "__main__":
# 創建一個 XMLReader
parser = xml.sax.make_parser()
# turn off namepsaces
parser.setFeature(xml.sax.handler.feature_namespaces, 0)
# 重寫 ContextHandler
Handler = CountryHandler()
parser.setContentHandler(Handler)
parser.parse("xml2obj.xml")
7、libxml2和lxml解析xml
libxml2是使用C語言開發的xml解析器,是一個基于MIT License的免費開源軟件,多種編程語言都有基于它的實現,python中的libxml2模塊有點小不足的是:xpathEval()接口不支持類似模板的用法,但不影響使用,因libxml2采用C語言開發的,因此在使用API接口的方式上難免會有點不適應。
在CODE上查看代碼片派生到我的代碼片
import libxml2
doc = libxml2.parseFile("xml2obj.xml")
for book in doc.xpathEval('//country'):
if book.content != "":
print("----------------------")
print(book.content)
for node in doc.xpathEval("http://country/neighbor[@name = 'Colombia']"):
print(node.name, (node.properties.name, node.properties.content))
doc.freeDoc()
案例
from lxml import etree
import requests
response = requests.get('https://www.baisu.com/).text
tree = etree.HTML(response)
strs = tree.xpath( "http://body")
strs = strs[0]
strs = (etree.tostring(strs)) # 不能正常顯示中文
strs = (etree.tostring(strs, encoding = "utf-8", pretty_print = True, method = "html")) # 可以正常顯示中文
print (strs)
總結
(1)Python中XML解析可用的類庫或模塊有xml、libxml2 、lxml 、xpath等,需要深入了解的還需參考相應的文檔。
(2)每一種解析方式都有自己的優點和缺點,選擇前可以綜合各個方面的性能考慮。
(3)若有不足,請留言,在此先感謝!
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
