Python實現XML文件解析

1. XML簡介

  XML(eXtensible Markup Language)指可擴展標記語言,被設計用來傳輸和存儲數據,已經日趨成爲當前許多新生技術的核心,在不一樣的領域都有着不一樣的應用。它是web發展到必定階段的必然產物,既具備SGML的核心特徵,又有着HTML的簡單特性,還具備明確和結構良好等許多新的特性。node

  test.XML文件 python

<?xml version="1.0" encoding="utf-8"?>
<catalog>
    <maxid>4</maxid>
    <login username="pytest" passwd='123456'>
        <caption>Python</caption>
        <item id="4">
            <caption>測試</caption>
        </item>
    </login>
    <item id="2">
        <caption>Zope</caption>
    </item>
</catalog>

  XML詳細介紹能夠參考:http://www.w3school.com.cn/xmldom/dom_nodetype.aspweb

2. XML文件解析

  python解析XML常見的有三種方法:一是xml.dom.*模塊,它是W3C DOM API的實現,若須要處理DOM API則該模塊很適合;二是xml.sax.*模塊,它是SAX API的實現,這個模塊犧牲了便捷性來換取速度和內存佔用,SAX是一個基於事件的API,這就意味着它能夠「在空中」處理龐大數量的的文檔,不用徹底加載進內存;三是xml.etree.ElementTree模塊(簡稱 ET),它提供了輕量級的Python式的API,相對於DOM來講ET 快了不少,並且有不少使人愉悅的API可使用,相對於SAX來講ET的ET.iterparse也提供了 「在空中」 的處理方式,沒有必要加載整個文檔到內存,ET的性能的平均值和SAX差很少,可是API的效率更高一點並且使用起來很方便。編程

2.1 xml.dom.*

  文件對象模型(Document Object Model,簡稱DOM),是W3C組織推薦的處理可擴展置標語言的標準編程接口。一個 DOM 的解析器在解析一個XML文檔時,一次性讀取整個文檔,把文檔中全部元素保存在內存中的一個樹結構裏,以後你能夠利用DOM 提供的不一樣的函數來讀取或修改文檔的內容和結構,也能夠把修改過的內容寫入xml文件。python中用xml.dom.minidom來解析xml文件。app

  a. 得到子標籤   

  b. 區分相同標籤名的標籤

  c. 獲取標籤屬性值

  d. 獲取標籤對之間的數據

#coding=utf-8

#經過minidom解析xml文件
import xml.dom.minidom as xmldom
import os
''' 
XML文件讀取 
<?xml version="1.0" encoding="utf-8"?>
<catalog>
    <maxid>4</maxid>
    <login username="pytest" passwd='123456'>dasdas
        <caption>Python</caption>
        <item id="4">
            <caption>測試</caption>
        </item>
    </login>
    <item id="2">
        <caption>Zope</caption>
    </item>
</catalog>

'''

xmlfilepath = os.path.abspath("test.xml")
print ("xml文件路徑:", xmlfilepath)

# 獲得文檔對象
domobj = xmldom.parse(xmlfilepath)
print("xmldom.parse:", type(domobj))
# 獲得元素對象
elementobj = domobj.documentElement
print ("domobj.documentElement:", type(elementobj))

#得到子標籤
subElementObj = elementobj.getElementsByTagName("login")
print ("getElementsByTagName:", type(subElementObj))

print (len(subElementObj))
# 得到標籤屬性值
print (subElementObj[0].getAttribute("username"))
print (subElementObj[0].getAttribute("passwd"))

#區分相同標籤名的標籤
subElementObj1 = elementobj.getElementsByTagName("caption")
for i in range(len(subElementObj1)):
    print ("subElementObj1[i]:", type(subElementObj1[i]))
    print (subElementObj1[i].firstChild.data)  #顯示標籤對之間的數據

  輸出結果:

>>> D:\Pystu>python xml_instance.py
>>> xml文件路徑: D:\Pystu\test.xml
>>> xmldom.parse: <class 'xml.dom.minidom.Document'>
>>> domobj.documentElement: <class 'xml.dom.minidom.Element'>
>>> getElementsByTagName: <class 'xml.dom.minicompat.NodeList'>
>>> username: pytest
>>> passwd: 123456
>>> subElementObj1[i]: <class 'xml.dom.minidom.Element'>
>>> Python
>>> subElementObj1[i]: <class 'xml.dom.minidom.Element'>
>>> 測試
>>> subElementObj1[i]: <class 'xml.dom.minidom.Element'>
>>> Zope

2.2 xml.etree.ElementTree

  ElementTree生來就是爲了處理XML,它在Python標準庫中有兩種實現:一種是純Python實現的,如xml.etree.ElementTree,另外一種是速度快一點的xml.etree.cElementTree。注意:儘可能使用C語言實現的那種,由於它速度更快,並且消耗的內存更少。dom

  a. 遍歷根節點的下一層   

  b. 下標訪問各個標籤、屬性、文本

  c. 查找root下的指定標籤

  d. 遍歷XML文件

  e. 修改XML文件

#coding=utf-8

#經過解析xml文件
'''
try:
    import xml.etree.CElementTree as ET
except:
    import xml.etree.ElementTree as ET

從Python3.3開始ElementTree模塊會自動尋找可用的C庫來加快速度    
'''
import xml.etree.ElementTree as ET
import os
import sys
''' 
XML文件讀取 
<?xml version="1.0" encoding="utf-8"?>
<catalog>
    <maxid>4</maxid>
    <login username="pytest" passwd='123456'>dasdas
        <caption>Python</caption>
        <item id="4">
            <caption>測試</caption>
        </item>
    </login>
    <item id="2">
        <caption>Zope</caption>
    </item>
</catalog>
'''

#遍歷xml文件
def traverseXml(element):
    #print (len(element))
    if len(element)>0:
        for child in element:
            print (child.tag, "----", child.attrib)
            traverseXml(child)
    #else:
        #print (element.tag, "----", element.attrib)
        

if __name__ == "__main__":
    xmlFilePath = os.path.abspath("test.xml")
    print(xmlFilePath)
    try:
        tree = ET.parse(xmlFilePath)
        print ("tree type:", type(tree))
    
        # 得到根節點
        root = tree.getroot()
    except Exception as e:  #捕獲除與程序退出sys.exit()相關以外的全部異常
        print ("parse test.xml fail!")
        sys.exit()
    print ("root type:", type(root))    
    print (root.tag, "----", root.attrib)
    
    #遍歷root的下一層
    for child in root:
        print ("遍歷root的下一層", child.tag, "----", child.attrib)

    #使用下標訪問
    print (root[0].text)
    print (root[1][1][0].text)

    print (20 * "*")
    #遍歷xml文件
    traverseXml(root)
    print (20 * "*")

    #根據標籤名查找root下的全部標籤
    captionList = root.findall("item")  #在當前指定目錄下遍歷
    print (len(captionList))
    for caption in captionList:
        print (caption.tag, "----", caption.attrib, "----", caption.text)

    #修改xml文件,將passwd修改成999999
    login = root.find("login")
    passwdValue = login.get("passwd")
    print ("not modify passwd:", passwdValue)
    login.set("passwd", "999999")   #修改,若修改text則表示爲login.text
    print ("modify passwd:", login.get("passwd"))
    

  輸出結果:

>>> D:\Pystu\test.xml
>>> tree type: <class 'xml.etree.ElementTree.ElementTree'>
>>> root type: <class 'xml.etree.ElementTree.Element'>
>>> catalog ---- {}
>>> 遍歷root的下一層 maxid ---- {}
>>> 遍歷root的下一層 login ---- {'username': 'pytest', 'passwd': '123456'}
>>> 遍歷root的下一層 item ---- {'id': '2'}
>>> 4
>>> 測試
>>> ********************
>>> maxid ---- {}
>>> login ---- {'username': 'pytest', 'passwd': '123456'}
>>> caption ---- {}
>>> item ---- {'id': '4'}
>>> caption ---- {}
>>> item ---- {'id': '2'}
>>> caption ---- {}
>>> ********************
>>> 1
>>> item ---- {'id': '2'} ----

>>> not modify passwd: 123456
>>> modify passwd: 999999

  附:

#coding=utf-8

'''
    XML解析類
    @功能-結點的增刪改查
'''
import xml.etree.ElementTree as ET
import sys
import os.path

class XmlParse:
    def __init__(self, file_path):
        self.tree = None
        self.root = None
        self.xml_file_path = file_path

    def ReadXml(self):
        try:
            print("xmlfile:", self.xml_file_path)
            self.tree = ET.parse(self.xml_file_path)
            self.root = self.tree.getroot()
        except Exception as e:
            print ("parse xml faild!")
            sys.exit()
        else:
            print ("parse xml success!")            
        finally: 
            return self.tree
               
    def CreateNode(self, tag, attrib, text):
        element = ET.Element(tag, attrib)
        element.text = text
        print ("tag:%s;attrib:%s;text:%s" %(tag, attrib, text))
        return element
              
    def AddNode(self, Parent, tag, attrib, text):
        element = self.CreateNode(tag, attrib, text)
        if Parent:
            Parent.append(element)
            el = self.root.find("lizhi")
            print (el.tag, "----", el.attrib, "----", el.text)
        else:
            print ("parent is none")

    def WriteXml(self, destfile):
        dest_xml_file = os.path.abspath(destfile)
        self.tree.write(dest_xml_file, encoding="utf-8",xml_declaration=True)
        

if __name__ == "__main__":
    xml_file = os.path.abspath("test.xml")
    parse = XmlParse(xml_file)
    tree = parse.ReadXml()
    root = tree.getroot()
    print (root)
    parse.AddNode(root, "Python", {"age":"22", "hello":"world"}, "YES")
    
    parse.WriteXml("testtest.xml")
View Code

2.3 xml.sax.*

  SAX是一種基於事件驅動的API,利用SAX解析XML牽涉到兩個部分:解析器和事件處理器。ide

  解析器負責讀取XML文檔,並向事件處理器發送事件,如元素開始跟元素結束事件函數

  事件處理器則負責對事件做出相應,對傳遞的XML數據進行處理性能

  經常使用場景:測試

    (1)對大型文件進行處理

    (2)只需文件的部份內容,或只需從文件中獲得特定信息

    (3)想創建本身的對象模型

  基於事件驅動的SAX解析XML內容的知識後續補充!
相關文章
相關標籤/搜索