在處理 Word (.docx) 或 Excel (.xlsx) 的底層結構時,
我們常會看到像「壓縮餅乾」一樣擠成一團的 XML 內容。
雖然使用 VS Code (Shift+Alt+F) 可以一鍵讓它變得賞心悅目,
但如果我們是在寫 Python 自動化腳本,
該怎麼讓輸出的檔案也擁有一樣漂亮的縮排呢?
Python 強大的 lxml 函式庫中的 pretty_print=True 參數,
就是程式碼界的「格式化文件」按鈕。

準備工作
首先,確保您的環境中已安裝 lxml。
它比 Python 內建的 xml 模組更快、功能更強大。
pip install lxml實戰教學:還原 document.xml.rels
假設我們有一個剛從 Word 解壓縮出來的 document.xml.rels 檔案,
內容擠在同一行。
我們目標是將其讀取並轉換為易讀格式。
核心程式碼
from lxml import etree
# 1. 模擬原始的 Minified XML 資料 (或是從檔案讀取)
# 這裡使用截圖中的結構作為範例
raw_xml = (
'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
'<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">'
'<Relationship Id="rId3" Type=".../webSettings" Target="webSettings.xml"/>'
'<Relationship Id="rId2" Type=".../settings" Target="settings.xml"/>'
'<Relationship Id="rId1" Type=".../styles" Target="styles.xml"/>'
'</Relationships>'
)
# 2. 解析 XML
# 注意:為了確保縮排能正確重置,建議設定 remove_blank_text=True
parser = etree.XMLParser(remove_blank_text=True)
root = etree.fromstring(raw_xml.encode('utf-8'), parser=parser)
# 3. 輸出漂亮的格式 (Pretty Print)
pretty_xml = etree.tostring(
root,
pretty_print=True, # <--- 這就是魔法關鍵
encoding='utf-8',
xml_declaration=True
).decode('utf-8')
print(pretty_xml)輸出:

進階技巧:直接處理檔案
如果您想直接讀取硬碟中的 document.xml.rels 並另存為格式化後的新檔,
可以使用 ElementTree 物件的操作方式:
from lxml import etree
input_file = 'document.xml.rels'
output_file = 'document_pretty.xml'
# 讀取檔案 (同樣建議移除既有的空白,以免干擾排版)
parser = etree.XMLParser(remove_blank_text=True)
tree = etree.parse(input_file, parser)
# 寫入新檔,並開啟 pretty_print
tree.write(
output_file,
pretty_print=True,
encoding='utf-8',
xml_declaration=True
)
print(f"轉換完成!請查看 {output_file}")輸出:

為什麼有時候 pretty_print 會失效?
很多新手會發現設了 True 卻沒反應。
這通常是因為原始 XML 中夾雜了原本的「換行符」或「空白」。lxml 會認為這些空白是文字內容的一部分,因此不敢隨意更動縮排。
解決方案:
如範例所示,在解析時加上 parser = etree.XMLParser(remove_blank_text=True),
告訴解析器:「忽略那些無意義的空白,全部由我重新排版!」
總結
- 手動查看:使用 VS Code (
Shift+Alt+F) 最快。 - 程式處理:使用 Python
lxml搭配pretty_print=True。
掌握這個技巧,無論是在 Debug 還是生成報表,
您的 XML 檔案都能保持專業且整潔的結構。
推薦hahow線上學習python: https://igrape.net/30afN
進階教學:關於 encoding='unicode' 與 xml_declaration=False
在 Python 3 的環境下開發時,
您會發現上述程式碼有一個小小的「累贅」動作:tostring(...).decode('utf-8')。
lxml 的 tostring 函式預設行為是產生 Bytes(二進位資料),
這是為了方便直接寫入檔案。
但如果您的目的是在程式內部處理字串
(例如存入資料庫、Regex 比對、或是單純 print 出來除錯),
使用 encoding='unicode' 會是更 Pythonic(符合 Python 風格)的做法。
以下是詳細解析:
1. 傳統寫法 vs. Pythonic 寫法
傳統寫法 (Bytes 轉 String):
這是原本的寫法,先轉成 bytes 再解碼。
# 產出 bytes,然後手動 decode
xml_bytes = etree.tostring(root, encoding='utf-8')
xml_str = xml_bytes.decode('utf-8')Pythonic 寫法 (直接產出 String):
直接告訴 lxml 我要的是 Python 的字串物件(Unicode)。
# 直接產出 str
xml_str = etree.tostring(root, encoding='unicode')2. 為什麼這通常搭配 xml_declaration=False?
當您設定 encoding='unicode' 時,通常建議同時設定 xml_declaration=False,原因如下:
- 邏輯上的矛盾:
XML 宣告中的encoding='UTF-8'是用來告訴解析器「這個檔案的Bytes是如何排列的」。
但如果您將encoding設為'unicode',回傳的是 Python 內部的字串物件(抽象的字符),此時它還沒有被編碼成具體的 Bytes。如果在一個 Python 字串開頭寫encoding='UTF-8',雖然語法上不一定報錯(手動拼接字串),但在邏輯上是沒有意義的,因為它現在是記憶體中的物件,不是檔案流。
在lxml中,encoding='unicode'與xml_declaration=True是互斥的,程式會直接 Crash,而不是僅僅「邏輯上無意義」。 - 字串處理的便利性:
在記憶體內處理字串時,那個<?xml ...?>頭通常只是干擾。使用encoding='unicode'的情境通常就是為了字串處理,因此把頭去掉能讓字串更乾淨。
為什麼會報錯?(技術原理)
ValueError: Serialisation to unicode must not request an XML declaration
這個錯誤訊息非常直白:「序列化為 Unicode 時,不可要求 XML 宣告。」
這背後的原因是 XML 宣告(XML Declaration)的本質與 Python 字串(Unicode) 存在根本性的衝突:
- XML 宣告的作用:例如
<?xml version='1.0' encoding='UTF-8'?>,這行字的主要目的是告訴接收者:「接下來的內容是一串 Bytes(位元組),請使用 UTF-8 編碼表將其解碼為字符。」 - encoding=’unicode’ 的作用:這告訴
lxml不要進行編碼(Encode),直接回傳 Python 內部的抽象字符物件(str)。
衝突點:
如果您要求 lxml 回傳一個 Python str(未編碼的抽象字符),卻又要求它加上一個 XML 宣告說「我是 UTF-8 編碼」,這就是說謊。因為這個 Python str 在記憶體中並不是 UTF-8 Bytes。
lxml 為了防止開發者產出這種「自我矛盾」的無效 XML 資料,因此在程式碼層面直接阻擋了這種組合。
3. 實戰範例
如果您只是想在 Console 印出來檢查結構,或是要將 XML 片段插入另一個大的 XML 中,這是最推薦的寫法:
# 乾淨、直接,回傳的是 str 類型
clean_xml_str = etree.tostring(
root,
pretty_print=True,
encoding='unicode', # 直接回傳字串,不用再 .decode()
xml_declaration=False # 既然是內部字串,就不需要宣告頭
)
print(type(clean_xml_str)) # <class 'str'>
print(clean_xml_str)輸出:

注意clean_xml_str最開頭少了:
<?xml version=’1.0′ encoding=’utf-8′?>
總結對照表

在 Python 程式碼運作中:
您可以放心地使用 xml_declaration=False,讓字串乾淨一點,
方便除錯或比對字串。
在最後存檔/輸出時:
如果是要寫回 .xml 檔案(特別是給 Word/Excel 用),
請務必在 tostring 時把 xml_declaration=True 加回去,
或是手動在字串最前面補上 <?xml version='1.0' encoding='utf-8'?>。
推薦hahow線上學習python: https://igrape.net/30afN










近期留言