天天看點

68.[Python]使用xml.etree.ElementTree操作XML簡介ElementTree與Elment解析XML周遊元素修改XML檔案使用iterparse處理大檔案

文章目錄

  • 簡介
  • ElementTree與Elment
  • 解析XML
  • 周遊元素
  • 修改XML檔案
  • 使用iterparse處理大檔案
轉載請注明原始連結: http://blog.csdn.net/a464057216/article/details/54915241

後續此部落格不再更新,歡迎大家搜尋關注微信公衆号“測開之美”,測試開發工程師技術修煉小站,持續學習持續進步。

68.[Python]使用xml.etree.ElementTree操作XML簡介ElementTree與Elment解析XML周遊元素修改XML檔案使用iterparse處理大檔案

簡介

XML是被設計用來傳輸和存儲資料的可擴充标記語言,Python中可以使用xml.etree.ElementTree操作XML檔案。

Python 2.7采用ElementTree 1.3版本。xml.etree.ElementTree的更高效、占用記憶體更少的C語言版本的實作是xml.etree.cElementTree。

ElementTree與Elment

XML按照樹型結構組織,ET有兩種類來表示這種組織結構:ElementTree表示整個XML樹,Element表示樹上的單個節點。操作整個XML文檔時使用ElementTree類,比如讀寫XML檔案。操作XML元素及其子元素時使用Element類。Element是一個靈活的容器對象,在記憶體中存儲階層化的資料結構。

每個元素包含如下屬性:

  • tag:表示元素類型的字元串。
  • attrib:以Python字典形式存儲的元素屬性。
  • text:開始标簽和第一個子元素之間的字元串或開始标簽和結束标簽之間的字元串或None。
  • tail:結束标簽和下一個标簽之間的字元串或None。
  • 子元素:以Python序列的形式存儲。

建立Element元素,使用Element()構造器或SubElement()工廠函數。

解析XML

比如test.xml内容為:

<?xml version="1.0"?>
<bookstore author="mars loo">
    <book>
        <name>LeaderF</name>
        <price>12.33</price>
    </book>
    <book>
        <name>YCM</name>
        <price>11.91</price>
    </book>
</bookstore>
           

可以調用ET.parse(filename)将XML文檔解析為ElementTree對象,調用ElementTree.getroot()擷取Element類型的樹根,然後分别通路樹根元素的tag、attrib、text、tail等屬性:

try:
    import xml.etree.cElementTree as ET
except ImportError:
    import xml.etree.ElementTree as ET

tree = ET.parse('test.xml')
root = tree.getroot()
print "Tag:", root.tag, "Attributes:", root.attrib, "Text:", root.text.strip(), "Tail:", root.tail
           

運作結果:

Tag: bookstore Attributes: {'author': 'mars loo'} Text:  Tail: None
           

注意,如果test.xml檔案的第2行是如下内容:

則上面的代碼中

root.text

的類型是None。

使用

tree = ET.ElementTree(file='test.xml')

與使用

tree = ET.parse('test.xml')

效果一樣。如果使用ET.fromstring()方法解析,則直接傳回Element類型的樹根元素。如果一個Element對象有子元素,可以直接周遊,也可以使用下标通路:

try:
    import xml.etree.cElementTree as ET
except:
    import xml.etree.ElementTree as ET

xml_string = '''<?xml version="1.0"?>
<bookstore author="mars loo">
    <book id="1">
        <name>LeaderF</name>
        <price>12.33</price>
    </book>
    <book id="2">
        <name>YCM</name>
        <price>11.91</price>
    </book>
</bookstore>'''

root = ET.fromstring(xml_string)
for child in root:
    print "Tag:", child.tag, "Attributes:", child.attrib
print "Book 2's price", root[1][1].text.strip()
           

運作結果:

Tag: book Attributes: {'id': '1'}
Tag: book Attributes: {'id': '2'}
Book 2's price 11.91
           

周遊元素

Element類和ElementTree類都有iter()方法可以遞歸周遊元素/樹的所有子元素,比如:

for child in root.iter(): //root是Element對象
    print "Tag:", child.tag, "Attributes:", child.attrib, "Text:", child.text.strip()
           

使用tag參數可以周遊指定tag的元素:

for child in tree.iter(tag='price'): //tree是ElementTree對象
     print "Tag:", child.tag, "Attributes:", child.attrib, "Text:", child.text.strip()
           

Element.findall(match)方法通過tag名字或xpath比對第一層子元素,按照子元素順序以清單形式傳回所有比對的元素。

Element.find(match)方法通過tag名字或xpath在第一層子元素中查找第一個比對的元素,傳回比對的元素或None。

Element.get(key, default=None)傳回元素名字為key的屬性值,如果沒有找到,傳回None或設定的預設值。

修改XML檔案

ElementTree.write(filename)方法可以友善的将ElementTree對象寫入XML檔案。

可以通過調用Element對象不同的方法修改Element對象,比如:

  • Element.text=value可以直接修改其text屬性。
  • Element.tail=value可以直接修改其tail屬性。
  • Element.set(key, vlaue)可以添加新的attrib。
  • Element.append(subelement)可以添加新的子元素。
  • Element.extend(subelements)添加子元素的清單(參數類型是序列)。
  • Element.remove(subelement)可以删除子元素。

将所有圖書的價格加1,給price元素增加一個

updated="true"

的屬性,同時增加一個内容為

"tail"

的tail:

tree = ET.parse('test.xml')
for child in tree.iter(tag = 'price'):
    child.text = str(float(child.text.strip()) + 1)
    child.tail = "tail"
    child.set("updated", "true")

tree.write('new.xml')
           

new.xml内容為:

<bookstore author="mars loo">
    <book>
        <name>LeaderF</name>
        <price updated="true">13.33</price>tail</book>
    <book>
        <name>YCM</name>
        <price updated="true">12.91</price>tail</book>
</bookstore>
           

将所有圖書元素的price元素删除,增加出版社press元素,press元素的text屬性内容是

CTS

bookstore = ET.parse('test.xml')
for book in bookstore.findall('book'):
    book.remove(book.find('price'))
    press = ET.Element('press')
    press.text = "CTS"
    book.append(press)
bookstore.write('new2.xml')
           

new2.xml内容為:

<bookstore author="mars loo">
    <book>
        <name>LeaderF</name>
        <press>CTS</press></book>
    <book>
        <name>YCM</name>
        <press>CTS</press></book>
</bookstore>
           

使用ET.SubElement(parent, tag_name)可以快速建立子元素關系,使用ET.dump(elem)可以輸出elem的内容到标準輸出(elem可以是一個Element對象或ElementTree對象):

root = ET.Element('root')
a = ET.SubElement(root, 'a')
b = ET.SubElement(root, 'b')
c = ET.SubElement(root, 'c')
tree = ET.ElementTree(root)

ET.dump(tree)
           

運作輸出:

使用iterparse處理大檔案

ET.parse(filename)一次性将整個XML檔案加載到記憶體,ET.iterparse(filename)采用增量形式加載XML資料,占據更小的記憶體空間。如果test.xml包含非常多本書我們想統計書本數量,可以采用iterparse()高效處理:

count = 0
for event, elem in ET.iterparse('test.xml'):
    if event == 'end':
        if elem.tag == "book":
            count += 1
    elem.clear() //重置元素(删除所有子元素、清除所有attrib、将text和tail設定為None)

print count
           
如果覺得我的文章對您有幫助,歡迎關注我(CSDN:Mars Loo的部落格)或者為這篇文章點贊,謝謝!