開始在 Python 中使用 XML 的一個主要要素是排列出所有可用模組的可比效能力。在他的新 Python 專欄“可愛的 Python”的第一部分中,David Mertz 簡要描述了最流行和實用的關於 XML 的 Python 模組,並指出可以下載的單獨模組以及可供閱讀的參考資料。本文有助於確定哪些模組最適合特定任務。
在許多情況下,Python 是使用 XML 文檔的理想語言。像 Perl、REBOL、REXX 和 TCL 一樣,它是一種靈活的指令碼語言,並且有強大的文本操作能力。而且,XML 文檔除了編碼大多數類型的文字檔(或流檔案),通常還編碼大量複雜的資料結構。文本處理中常見的“讀取幾行,並將它們與一些規則運算式比較”樣式通常不能很好地適合對 XML 進行徹底文法分析和處理。幸好,Python(與大多數其它語言相比)不僅有直接處理複雜資料結構的方法(通常使用類和屬性),還有許多 XML 相關的模組可以協助文法分析、處理和產生 XML。
關於 XML,要記住一個總體概念:可以驗證或非驗證方式處理 XML 文檔。在以前的處理類型中,讀取 XML 文檔之前,必須先讀取“文件類型定義”(DTD)。這種情況下,處理將總體計算 XML 文檔的簡單句型規則,還將計算 DTD 的特定文法約束。大多數情況下,使用非驗證處理就可以了(通常運行更快,更適合程式) -- 我們相信文檔建立者遵循文檔範圍的規則。在下面討論的大多數模組都是非驗證型;如果存在驗證選項,則描述將指出。
中心資產庫 (Vaults of Parnassus)(請參閱 參考資料)最近已成為尋找 Python 資源的標準方法。可以在那個網站上找到所有以下討論的模組(通過連結到各自模組所有者的網站)。特別地,可以在資產庫中找到 PyXML 發行版,它是 tar 檔案和 Win32 形式的安裝程式。
Python 的 XML 特殊興趣組 (XML-SIG)
XML-SIG 的成員執行了許多 -- 或大部分 -- 維護 Python 一部分 XML 工具的任務。與其它 Python SIG 一樣,XML-SIG 要維護郵件發送列表、列表檔案、有用的參考大權、文檔、標準包和其它資源。閱讀了本文中的概述後,最好從 XML-SIG Web 頁面入手。
根據本文中講述的特定重點,XML-SIG 維護了 PyXML 發行版。這個包包含了許多本文中討論的模組,一些“入門”文檔,一些示範代碼和其它一些 XML-SIG 決定放入該發行版的東西。給定的包也許不會總是包含每個獨立模組或工具的最新版本,但下載 PyXML 發行版是個好主意。以後,可以隨時添加任何未包含的模組,或者已包含模組的新版本(以及許多 PyXML 發行版提供的服務所未包含的模組)。
模組:XMLLIB 模組(標準)
“不包括在標準發行版中”,Python 1.5.* 帶有模組 [xmllib]。Python 1.6 也許結合了更多 XML-SIG 的成就,但它仍是測試版。[xmllib] 是一個非驗證的低級文法分析器。[xmllib] 的工作方式是用應用程式覆蓋 XMLParser 類,並提供處理文件項目(如特定或類屬標記,或字元實體)的方法。
作為正在使用的 [xmllib] 樣本,PyXML 發行版包括一個叫做 'quotations.dtd' 的 DTD,以及這個 DTD 的文檔 'sample.xml'(請參閱 參考資料,以擷取本文中提到的檔案的檔案檔案)。以下的代碼顯示了 'sample.xml' 中每段引言的前幾行,並產生了非常簡單的未知標記和實體的 ASCII 指示符。經過分析的文本作為連續流來處理,所使用的任何累加器都由程式員負責(如標記中的字串 (#PCDATA),或所遇到的標記的列表/詞典)。
嘗試 xmllib 的代碼
#-------------------- try_xmllib.py --------------------# import xmllib, string class QuotationParser(xmllib.XMLParser): """Crude xmllib extractor for quotations.dtd document""" def __init__(self): xmllib.XMLParser.__init__(self) self.thisquote = '' # quotation accumulator def handle_data(self, data): self.thisquote = self.thisquote + data def syntax_error(self, message): pass def start_quotations(self, attrs): # top level tag print '--- Begin Document ---' def start_quotation(self, attrs): print 'QUOTATION:' def end_quotation(self): print string.join(string.split(self.thisquote[:230]))+'...', print '('+str(len(self.thisquote))+' bytes)\n' self.thisquote = '' def unknown_starttag(self, tag, attrs): self.thisquote = self.thisquote + '{' def unknown_endtag(self, tag): self.thisquote = self.thisquote + '}' def unknown_charref(self, ref): self.thisquote = self.thisquote + '?' def unknown_entityref(self, ref): self.thisquote = self.thisquote + '#' if __name__ == '__main__': parser = QuotationParser() for c in open("sample.xml").read(): parser.feed(c) parser.close()