|
在許多情況下,Python 是使用 XML 文檔的理想語言。像 Perl、REBOL、REXX 和 TCL 一樣,它是一種靈活的腳本語言,并且有強大的文本操作能力。而且,XML 文檔除了編碼大多數(shù)類型的文本文件(或流文件),通常還編碼大量復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。文本處理中常見的“讀取幾行,并將它們與一些規(guī)則表達式比較”樣式通常不能很好地適合對 XML 進行徹底語法分析和處理。幸好,Python(與大多數(shù)其它語言相比)不僅有直接處理復(fù)雜數(shù)據(jù)結(jié)構(gòu)的方法(通常使用類和屬性),還有許多 XML 相關(guān)的模塊可以幫助語法分析、處理和生成XML。 關(guān)于 XML,要記住一個總體概念:可以驗證或非驗證方式處理 XML 文檔。在以前的處理類型中,讀取 XML 文檔之前,必須先讀取“文檔類型定義”(DTD)。這種情況下,處理將總體計算 XML 文檔的簡單句型規(guī)則,還將計算 DTD 的特定語法約束。大多數(shù)情況下,使用非驗證處理就可以了(通常運行更快,更適合程序) -- 我們相信文檔創(chuàng)建者遵循文檔范圍的規(guī)則。在下面討論的大多數(shù)模塊都是非驗證型;如果存在驗證選項,則描述將指出。 中心資源庫 (Vaults of Parnassus)最近已成為查找 Python 資源的標準方法??梢栽谀莻€站點上找到所有以下討論的模塊。特別地,可以在資源庫中找到 PyXML 發(fā)行版,它是 tar 文件和 Win32 形式的安裝程序。 Python 的 XML 特殊興趣組 (XML-SIG) XML-SIG 的成員執(zhí)行了許多 -- 或大部分 -- 維護 Python 一部分 XML 工具的任務(wù)。與其它 Python SIG 一樣,XML-SIG 要維護郵件發(fā)送列表、列表檔案、有用的參考大權(quán)、文檔、標準包和其它資源。閱讀了本文中的概述后,最好從 XML-SIG Web 頁面入手。 根據(jù)本文中講述的特定重點,XML-SIG 維護了 PyXML 發(fā)行版。這個包包含了許多本文中討論的模塊,一些“入門”文檔,一些演示代碼和其它一些 XML-SIG 決定放入該發(fā)行版的東西。給定的包也許不會總是包含每個獨立模塊或工具的最新版本,但下載 PyXML 發(fā)行版是個好主意。以后,可以隨時添加任何未包含的模塊,或者已包含模塊的新版本(以及許多 PyXML 發(fā)行版提供的服務(wù)所未包含的模塊)。 模塊:XMLLIB 模塊(標準) “不包括在標準發(fā)行版中”,Python 1.5.* 帶有模塊 [xmllib]。Python 1.6 也許結(jié)合了更多 XML-SIG 的成就,但它仍是測試版。[xmllib] 是一個非驗證的低級語法分析器。[xmllib] 的工作方式是用應(yīng)用程序覆蓋 XMLParser 類,并提供處理文檔元素(如特定或類屬標記,或字符實體)的方法。 作為正在使用的 [xmllib] 示例,PyXML 發(fā)行版包括一個叫做 ‘quotations.dtd‘ 的 DTD,以及這個 DTD 的文檔 ‘sample.xml‘。以下的代碼顯示了 ‘sample.xml‘ 中每段引言的前幾行,并生成了非常簡單的未知標記和實體的 ASCII 指示符。經(jīng)過分析的文本作為連續(xù)流來處理,所使用的任何累加器都由程序員負責(如標記中的字符串 (#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)‘ 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() 其它語法分析模塊 PyXML 發(fā)行版包含了幾個具有各種功能的附加語法分析模塊。提供這些模塊是為了對基本 [xmllib] 模塊做一些改進。 [pyexpat] 是 GPL 方式的 XML 語法分析器工具箱 ‘expat‘ 的封裝程序。‘expat‘ 是用 C 語言寫的庫,這就意味著任何想要利用它的語言都可以使用它。‘expat‘ 是非驗證型,因此它比原來的 Python 語法分析器快很多。[sgmlop] 的目的與 [pyexpat] 相同。它也是非驗證型,而且也用 C 語言編寫。[pyexpat] 可以作為 MacOS 二進制使用,[sgmlop] 可以當作 Win32 二進制使用;但如果您需要使用不同的平臺,那么就要用 C 編譯器為您自己的平臺構(gòu)建模塊。 [xmlproc] 是 python 原有的語法分析器,它執(zhí)行幾乎完整的驗證。如果需要驗證型語法分析器, [xmlproc] 是 Python 當前唯一的選擇。同樣,[xmlproc] 提供其它語法分析器所不具備的各種高級和測試接口。 如果決定使用 XML 的簡單 API (SAX) -- 它應(yīng)該用于復(fù)雜的事物,因為其它大部分工具都構(gòu)建在它之上 -- 將為您完成許多語法分析器的分類工作。在 PyXML 發(fā)行版中,[xml.sax.drivers] 包含許多語法分析器的瘦封裝程序,包括所有那些已討論過的、名稱形式為 ‘drv_*.py‘ 的語法分析器。但是,一般使用高級 SAX 設(shè)施訪問驅(qū)動器,該設(shè)施自動選擇系統(tǒng)上“最佳”的可用語法分析器: 選擇語法分析器 #------------- selecting the best parser ---------------# from xml.sax.saxext import * parser = XMLParserFactory.make_parser() 包:SAX 以上,我們已提到 SAX 會自動選擇要使用的語法分析器;但 SAX 是什么?一個較好的答案是: “SAX(XML 的簡單 API)是 XML 語法分析器的公用語法分析器接口。它允許應(yīng)用程序作者編寫使用 XML 語法分析器的應(yīng)用程序,但是它卻獨立于所使用的語法分析器。(將它看作 XML 的 JDBC。)” -- Lars Marius Garshol, SAX for Python SAX -- 如同它提供的語法分析器模塊的 API -- 基本上是一個 XML 文檔的順序處理器。使用它的方法與 [xmllib] 示例極其相似,但更加抽象。定義語法分析器類,應(yīng)用程序員將定義一個 ‘handler‘ 類,該類將注冊所使用的語法分析器。必須定義四個 SAX 接口(每個接口都有幾個方法):documentHandler、DTDHandler、EntityResolver 和 ErrorHandler。已提供了所有這些接口的基類,但大多數(shù)情況下,最簡單的方法是繼承 ‘HandlerBase‘,因為這個類繼承了所有四個接口??梢圆挥每紤]想要做什么。某些代碼將幫助解釋這一點;該樣本執(zhí)行與 [xmllib] 示例相同的任務(wù)。 嘗試 SAX 的樣本代碼 #--------------------- try_sax.py ----------------------# import string from xml.sax import saxlib, saxexts class QuotationHandler(saxlib.HandlerBase): """Crude sax extractor for quotations.dtd document""" def __init__(self): self.in_quote = 0 self.thisquote = ‘‘ def startdocument(self): print ‘--- Begin document ---‘ def startElement(self, name, attrs): if name == ‘quotation‘: print ‘QUOTATION:‘ self.in_quote = 1 else: self.thisquote = self.thisquote + ‘{‘ def endElement(self, name): if name == ‘quotation‘: print string.join(string.split(self.thisquote[:230]))+‘...‘, print ‘(‘+str(len(self.thisquote))+‘ bytes)‘ self.thisquote = ‘‘ self.in_quote = 0 else: self.thisquote = self.thisquote + ‘}‘ def characters(self, ch, start, length): if self.in_quote: self.thisquote = self.thisquote + ch[start:start+length] if __name__ == ‘__main__‘: parser = saxexts.XMLParserFactory.make_parser() handler = QuotationHandler() parser.setdocumentHandler(handler) parser.parseFile(open("sample.xml")) parser.close() 與 [xmllib] 相比,關(guān)于示例要注意兩件小事:‘parseFile()‘/‘parse()‘ 方法處理整個流/字符串,所以不必為語法分析器創(chuàng)建循環(huán);向 ‘characters()‘ 提供了大量數(shù)據(jù),自變量會指出數(shù)據(jù)的大小和位置以及傳遞的字符串。不要假設(shè)變量 ‘ch‘ 將以什么形式傳送給 ‘characters()‘。 包:DOM DOM 是一種 XML 文檔的高級樹型表示。該模型并非特定于 Python,而是一種普通 XML 模型。Python 的 DOM 包是針對 SAX 構(gòu)建的,并且包括在 PyXML 發(fā)行版中。由于篇幅關(guān)系,沒有將代碼樣本加到本文中,但在 XML-SIG 的 "Python/XML HOWTO" 中給出了一個極好的總體描述。 “文檔對象模型”(DOM) 為 XML 文檔指定了樹型表示。頂級文檔實例是樹的根,它只有一個子代,即頂級元素實例;這個元素有表示內(nèi)容和子元素的子節(jié)點,他們也可以有子代。定義的函數(shù)允許隨意遍歷結(jié)果樹,訪問元素和屬性值,插入和刪除節(jié)點,以及將樹轉(zhuǎn)換回 XML。 DOM 可以用于修改 XML 文檔,因為可以創(chuàng)建一棵 DOM 樹,通過添加新節(jié)點和來回移動子樹來修改這棵樹,然后生成一個新的 XML 文檔作為輸出。您也可以自己構(gòu)造一棵 DOM 樹,然后將它轉(zhuǎn)換成 XML;用這種方法生成 XML 輸出比僅將 ... 寫入文件的方法更靈活。 包:Pyxie [pyxie] 模塊從 XML-SIG 構(gòu)建到 PyXML 發(fā)行版之上,它為 XML 文檔提供了附加的高級接口。[pyxie] 將完成兩項基本操作:它將 XML 文檔轉(zhuǎn)換成一種更易于進行語法分析的基于行的格式;并且它提供了將 XML 文檔當作可操作樹處理的方法。[pyxie] 所使用的基于行的 PYX 格式是獨立于語言的,其工具適用于幾種語言??傊臋n的 PYX 表示與其 XML 表示相比,更易于使用常見的基于行的文本處理工具進行處理,如 grep、sed、awk、bash、perl,或標準 python 模塊,如 [string] 和 [re]。根據(jù)結(jié)果,從 XML 轉(zhuǎn)換到 PYX 可能節(jié)省許多工作。 [pyxie] 將 XML 文檔當作樹處理的概念與 DOM 中的思路相似。由于 DOM 標準得到許多編程語言的廣泛支持,那么如果 XML 文檔的樹型表示是必需的,大多數(shù)程序員會使用 DOM 標準而非 [pyxie]。 模塊:XML 語法分析器 “XML 語法分析器”這個叫法太籠統(tǒng),也許還不太確切,實際上它是一種比較舊的工具,用于檢查 XML 文檔是否符合句法以及其結(jié)構(gòu)是否完好(但對于 DTD 無效)。一個附加的實用程序類在進行檢查時會產(chǎn)生一些小麻煩,它會讓 HTML 文檔通過檢查(即使那些文檔沒有 XML 必需的結(jié)束標記)。這個模塊的適用范圍并不能覆蓋 PyXML 發(fā)行版中的所有模塊。但如果只想驗證一些 XML 文檔,那么設(shè)置和運行 XML 語法分析器還是很容易的。如果從命令行運行,則該模塊將在 STDIN 上檢查 XML 文檔,甚至不用將它導(dǎo)入程序。這是最簡單的做法。 XML_OBJECTS 0.1 如同其它高級工具,xml_objects 構(gòu)建在 SAX 之上。構(gòu)建 xml_objects 的目的是將 XML 文檔轉(zhuǎn)換成一個兩維網(wǎng)格表示,從而更易于在關(guān)系數(shù)據(jù)庫中存儲。 下一步 在下一個“可愛的 Python”專欄中,我們將進一步研究 xml.dom 模塊,它可能是 Python 程序員用來處理 XML 文檔的功能最強大的工具。 |
|
|