• 跳至主要導覽
  • 跳至主要內容
  • 跳至主要資訊欄
Office 指南

Office 指南

辦公室工作實用教學

  • Excel
  • Word
  • PowerPoint
  • Windows
  • PowerShell
  • R

Python 讀取、寫入 XML 格式檔案教學與範例

介紹如何在 Python 中使用 xml.etree.ElementTree 模組來讀取與寫入 XML 格式的資料與檔案。


在 Python 中如果需要讀取 XML 檔案,或是將資料寫入 XML 檔案中,可以使用 xml.etree.ElementTree 模組來處理,以下是此模組的使用方式與範例。

讀取 XML 檔案

假設有一個 XML 檔案 country_data.xml 內容如下:

<?xml version="1.0"?>
<data>
    <country name="Liechtenstein">
        <rank>1</rank>
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Austria" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
    </country>
    <country name="Singapore">
        <rank>4</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N"/>
    </country>
    <country name="Panama">
        <rank>68</rank>
        <year>2011</year>
        <gdppc>13600</gdppc>
        <neighbor name="Costa Rica" direction="W"/>
        <neighbor name="Colombia" direction="E"/>
    </country>
</data>

在讀取 XML 格式的資料時,可以直接從 *.xml 檔案載入,或是從字串中取得:

import xml.etree.ElementTree as ET

# 從檔案載入並解析 XML 資料
tree = ET.parse('country_data.xml')
root = tree.getroot()

# 從字串中取得並解析 XML 資料
root = ET.fromstring(country_data_as_string)

這裡產生的 root 是一個 Element 物件,代表 XML 的根節點,每一個 Element 物件都有 tag 與 attrib 兩個屬性:

# 節點 tag 屬性
print(root.tag)
data
# 節點 attrib 屬性
print(root.attrib)
{}

透過 for 迴圈可以列出所有的子節點:

# 子節點與屬性
for child in root:
    print(child.tag, child.attrib)
country {'name': 'Liechtenstein'}
country {'name': 'Singapore'}
country {'name': 'Panama'}

也可以使用索引的方式存取任意的節點,透過 text 屬性即可取得節點的內容:

# 使用索引存取節點
print(root[0][1].text)
2008

亦可透過 get 直接取得指定的屬性值:

# 取得指定的屬性值
print(root[0][3].get('name'))
Austria

尋找 XML 節點

iter 可以在指定節點之下,以遞迴方式搜尋所有子節點:

# 搜尋所有子節點
for neighbor in root.iter('neighbor'):
    print(neighbor.attrib)
{'name': 'Austria', 'direction': 'E'}
{'name': 'Switzerland', 'direction': 'W'}
{'name': 'Malaysia', 'direction': 'N'}
{'name': 'Costa Rica', 'direction': 'W'}
{'name': 'Colombia', 'direction': 'E'}

findall 與 find 則是只從第一層子節點中搜尋(不包含第二層以下),findall 會傳回所有結果,而 find 則是只傳回第一個找到的節點:

# 只從第一層子節點中搜尋,傳回所有找到的節點
for country in root.findall('country'):

    # 只從第一層子節點中搜尋,傳回第一個找到的節點
    rank = country.find('rank').text

    # 取得節點指定屬性質
    name = country.get('name')

    print(name, rank)
Liechtenstein 1
Singapore 4
Panama 68

修改 XML 資料

XML 節點的資料可以透過 Element.text 來修改,而屬性值則可以使用 Element.set() 來指定,若要將修改的結果寫入 XML 檔案,則可使用 ElementTree.write():

# 尋找 rank 節點
for rank in root.iter('rank'):
    # 將 rank 的數值加 1
    new_rank = int(rank.text) + 1

    # 設定新的 rank 值
    rank.text = str(new_rank)

    # 增加一個 updated 屬性值
    rank.set('updated', 'yes')

# 寫入 XML 檔案
tree.write('output.xml')

編輯之後的 XML 檔案內容會像這樣:

<?xml version="1.0"?>
<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Austria" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N"/>
    </country>
    <country name="Panama">
        <rank updated="yes">69</rank>
        <year>2011</year>
        <gdppc>13600</gdppc>
        <neighbor name="Costa Rica" direction="W"/>
        <neighbor name="Colombia" direction="E"/>
    </country>
</data>

若要移除 XML 的節點,可以使用 Element.remove():

# 在第一層子節點鐘尋找 country 節點
for country in root.findall('country'):
    # 取得 rank 數值
    rank = int(country.find('rank').text)

    # 若 rank 大於 50,則移除此節點
    if rank > 50:
        root.remove(country)

# 寫入 XML 檔案
tree.write('output.xml')

移除節點之後的 XML 檔案內容會像這樣:

<?xml version="1.0"?>
<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Austria" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N"/>
    </country>
</data>

建立 XML 結構

若要建立一個全新的 XML 結構,可以使用 Element 建立根節點,再以 SubElement() 加入子節點:

# 建立新的 XML 結構
orders = ET.Element('orders')

# 新增節點
order1 = ET.SubElement(orders, 'order')
order1.text = "My Order 1"
order1.set("new", "yes")

# 新增節點
order2 = ET.SubElement(orders, 'order')
order2.text = "My Order 2"
order2.set("new", "no")

# 輸出 XML 原始資料
ET.dump(orders)
<orders><order new="yes">My Order 1</order><order new="no">My Order 2</order></orders>

XPath 搜尋

XPath 可以讓使用者在 XML 結構中以較複雜的條件進行搜尋,以下是一些常見的範例。

# 頂層節點
root.findall(".")

# 尋找「頂層節點 => country => neighbor」這樣結構的節點
root.findall("./country/neighbor")

# 尋找 name 屬性為 Singapore,且含有 year 子節點的節點
root.findall(".//year/..[@name='Singapore']")

# 尋找父節點 name 屬性為 Singapore 的 year 節點
root.findall(".//*[@name='Singapore']/year")

# 尋找在同一層 neighbor 節點中排在第二位的那一個
root.findall(".//neighbor[2]")

XML 排版

若要對一般的 XML 檔案內容進行自動排版,可以使用 lxml 模組的 etree:

import lxml.etree as etree

# 讀取 XML 檔案
root = etree.parse("country_data.xml")

# 輸出排版的 XML 資料
print(etree.tostring(root, pretty_print=True, encoding="unicode"))

# 將排版的 XML 資料寫入檔案
root.write("pretty_print.xml", encoding="utf-8")

分類:Python

讀者互動方式

發佈留言 取消回覆

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

主要資訊欄

搜尋

近期文章

  • C++ 語言使用 Crypto++ 實作 RSA 數位簽章教學與範例
  • C++ 語言使用 Crypto++ 實作 RSA-OAEP 搭配 SHA256 加密教學與範例
  • C++ 語言使用 Crypto++ 實作 AES 加密、解密、認證加密教學與範例
  • C++ 語言使用 Crypto++ 實作 MD5、SHA1、SHA2、BLAKE2 雜湊教學與範例
  • Ubuntu Linux 安裝、使用 Crypto++ 加密函式庫教學與範例
  • C 語言使用 OpenSSL 實作橢圓曲線 ECDH 金鑰交換教學與範例
  • Python 以 eciespy 實作 ECC 非對稱式加密方法教學與範例
  • C 語言使用 OpenSSL 實作 PBKDF2 教學與範例

推薦網站

  • Udemy 線上教學課程
  • Coursera 線上教學課程

關注本站

  • 電子郵件
  • Facebook

公益

  • 家扶基金會
  • 台灣世界展望會
  • Yahoo 奇摩公益
  • igiving 公益網
  • 兒福聯盟

Copyright © 2021 · Office Guide