国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Python:使用基于事件驅動的SAX解析XML

2019-11-14 17:40:22
字體:
來源:轉載
供稿:網友

SAX的特點:

  • 是基于事件的 API
  • 在一個比 DOM 低的級別上操作
  • 為您提供比 DOM 更多的控制
  • 幾乎總是比 DOM 更有效率
  • 但不幸的是,需要比 DOM 更多的工作

基于對象和基于事件的接口

您可能已經知道語法分析器有兩類接口 - 基于對象的(如:DOM)和基于事件(如:SAX)的接口。

DOM是基于對象的語法分析器的標準 API。

作為基于對象的接口,DOM 通過在內存中顯示地構建對象樹來與應用程序通信。對象樹是 xml 文件中元素樹的精確映射。

DOM 易于學習和使用,因為它與基本 XML 文檔緊密匹配。然而,對于大多數應用程序,處理 XML 文檔只是其眾多任務中的一種。例如,記帳軟件包可能導入 XML 發票,但這不是其主要活動。計算帳戶余額、跟蹤支出以及使付款與發票匹配才是主要活動。記帳軟件包可能已經具有一個數據結構(最有可能是數據庫)。DOM 模型不太適合記帳應用程序,因為在那種情況下,應用程序必須在內存中維護數據的兩份副本(一個是 DOM 樹,另一個是應用程序自己的結構)。至少,在內存維護兩次數據會使效率下降。對于桌面應用程序來說,這可能不是主要問題,但是它可能導致服務器癱瘓。

對于不以 XML 為中心的應用程序,SAX 是明智的選擇。實際上,SAX 并不在內存中顯式地構建文檔樹。它使應用程序能用最有效率的方法存儲數據。

基于事件驅動

基于事件的語法分析器將事件發送給應用程序。這些事件類似于用戶界面事件,例如,瀏覽器中的 ONCLICK 事件或者 java 中的 AWT/Swing 事件。

事件通知應用程序發生了某件事并需要應用程序作出反應。在瀏覽器中,通常為響應用戶操作而生成事件:當用戶單擊按鈕時,按鈕產生一個 ONCLICK 事件。

在 XML 語法分析器中,事件與用戶操作無關,而與正在讀取的 XML 文檔中的元素有關。有對于以下方面的事件:

  • 元素開始和結束標記
  • 元素內容
  • 實體
  • 語法分析錯誤

圖 3 顯示語法分析器在讀取文檔時如何生成事件。

清單 1 顯示了 XML 格式的清單。它詳細列出了不同公司對 XML 培訓的收費。圖 4 顯示了價目表文檔的結構。

清單 1. PRicelist.xml
<?xml version="1.0"?><xbe:price-list xmlns:xbe="http://www.psol.com/xbe2/listing8.1">   <xbe:product>XML Training</xbe:product>   <xbe:price-quote price="999.00"  vendor="Playfield Training"/>   <xbe:price-quote price="699.00"  vendor="XMLi"/>   <xbe:price-quote price="799.00"  vendor="WriteIT"/>   <xbe:price-quote price="1999.00" vendor="Emailaholic"/></xbe:price-list>
圖 4. 價目表的結構

XML 語法分析器讀取并解釋該文檔。每當它識別出文檔中的某些內容,就會生成一個事件。

讀取 清單 1 時,語法分析器首先讀取 XML 聲明并生成文檔開始事件。當它遇到第一個開始標記 <xbe:price-list> 時,語法分析器生成它的第二個事件來通知應用程序已經遇到了 price-list 元素。

接下來,語法分析器看到 product 元素的開始標記(為簡單起見,在本文其余部分,我將忽略名稱空格和縮進空格)并生成它的第三個事件。

在開始標記后,語法分析器看到 product 元素的內容: XML Training ,它產生另一個事件。

下一個事件指出 product 元素的結束標記。語法分析器已經完成了對 product 元素的語法分析。到目前為止,它已經激發了 5 個事件: product 元素的 3 個事件,一個文檔開始事件和一個 price-list 開始標記事件。

語法分析器現在移動到第一個 price-quote 元素。它為每個 price-quote 元素生成兩個事件:一個開始標記事件和一個結束標記事件。

是的,即使將結束標記簡化為開始標記中的 / 字符,語法分析器仍然生成一個結束事件。

有 4 個 price-quote 元素,所以語法分析器在分析它們時生成 8 個事件。最后,語法分析器遇到 price-list 的結束標記并生成它的最后兩個事件:結束 price-list 和文檔結束。

如圖 5 所示,這些事件共同向應用程序描述了文檔樹。開始標記事件意味著“轉到樹的下一層”,而結束標記元素意味著“轉到樹的上一層”。

圖 5. 語法分析器如何隱含地構建樹

請注意,語法分析器傳遞了足夠信息以構建 XML 文檔的文檔樹,但是與 DOM 語法分析器不同,它并不顯式地構建該樹。

為何選擇SAE而不是DOM

現在,我敢肯定你已經糊涂了。應該使用哪一種類型的 API,應該何時使用它 - SAX 還是 DOM?不幸的是,這個問題沒有明確的答案。這兩種 API 中沒有一種在本質上更好;他們適用于不同的需求。

經驗法則是在需要更多控制時使用 SAX;要增加方便性時,則使用 DOM。

例如,DOM 在腳本語言中很流行。

采用 SAX 的主要原因是效率。SAX 比 DOM 做的事要少,但提供了對語法分析器的更多控制。當然,如果語法分析器的工作減少,則意味著您(開發者)有更多的工作要做。

而且,正如我們已討論的,SAX 比 DOM 消耗的資源要少,這只是因為它不需要構建文檔樹。

在 XML 早期,DOM 得益于 W3C 批準的官方 API 這一身份。逐漸地,開發者選擇了功能性而放棄了方便性,并轉向了 SAX。

SAX 的主要限制是它無法向后瀏覽文檔。實際上,激發一個事件后,語法分析器就將其忘記。如您將看到的,應用程序必須顯式地緩沖其感興趣的事件。

 


 

使用Python解析XML的時候,需要 import xml.sax 和 xml.sax.handler

xml.sax

xml.sax提供了3個函數以及 SAX 異常類

make_parser方法

創建并返回一個SAX XMLReader對象

xml.sax.make_parser([parser_list])

  • parser_list - 可選參數,解析器列表
parse方法

創建一個 SAX 解析器并解析xml文檔

xml.sax.parse(filename_or_stream, handler[, error_handler])  

  • file_or_stream:xml文件名
  • handler:必須是一個ContentHandler的對象
  • error_handler:如果指定該參數,errorhandler必須是一個SAX ErrorHandler對象
parseString方法

創建一個XML解析器并解析xml字符串

xml.sax.parseString(string, handler[, error_handler])

  • string: xml字符串
  • handler:必須是一個ContentHandler的對象
  • error_handler:如果指定該參數,errorhandler必須是一個SAX ErrorHandler對象

 

ContentHandler類方法介紹

  • characters(content)方法
    • 調用時機
    • 從行開始,遇到標簽之前,存在字符,content的值為這些字符串。
    • 從一個標簽,遇到下一個標簽之前, 存在字符,content的值為這些字符串。
    • 從一個標簽,遇到行結束符之前,存在字符,content的值為這些字符串。
    • 標簽可以是開始標簽,也可以是結束標簽。
  • startDocument()方法:文檔啟動的時候調用。
  • endDocument()方法:解析器到達文檔結尾時調用。
  • startElement(name, attrs)方法:遇到XML開始標簽時調用,name是標簽的名字,attrs是標簽的屬性值字典。
  • endElement(name)方法:遇到XML結束標簽時調用。

Python 解析XML實例

要解析的XML

 1 <?xml version="1.0"?> 2 <collection shelf="New Arrivals"> 3     <movie title="Enemy Behind"> 4        <type>War, Thriller</type> 5        <format>DVD</format> 6        <year>2003</year> 7        <rating>PG</rating> 8        <stars>10</stars> 9        <description>Talk about a US-Japan war</description>10     </movie>11     <movie title="Transformers">12        <type>Anime, Science Fiction</type>13        <format>DVD</format>14        <year>1989</year>15        <rating>R</rating>16        <stars>8</stars>17        <description>A schientific fiction</description>18     </movie>19        <movie title="Trigun">20        <type>Anime, Action</type>21        <format>DVD</format>22        <episodes>4</episodes>23        <rating>PG</rating>24        <stars>10</stars>25        <description>Vash the Stampede!</description>26     </movie>27     <movie title="Ishtar">28        <type>Comedy</type>29        <format>VHS</format>30        <rating>PG</rating>31        <stars>2</stars>32        <description>Viewable boredom</description>33     </movie>34 </collection>

使用SAX解析XML的Python源代碼

 1 #!/usr/bin/python 2  3 import xml.sax 4  5 class MovieHandler( xml.sax.ContentHandler ): 6    def __init__(self): 7       self.CurrentData = "" 8       self.type = "" 9       self.format = ""10       self.year = ""11       self.rating = ""12       self.stars = ""13       self.description = ""14 15    # 元素開始事件處理16    def startElement(self, tag, attributes):17       self.CurrentData = tag18       if tag == "movie":19          print "*****Movie*****"20          title = attributes["title"]21          print "Title:", title22 23    # 元素結束事件處理24    def endElement(self, tag):25       if self.CurrentData == "type":26          print "Type:", self.type27       elif self.CurrentData == "format":28          print "Format:", self.format29       elif self.CurrentData == "year":30          print "Year:", self.year31       elif self.CurrentData == "rating":32          print "Rating:", self.rating33       elif self.CurrentData == "stars":34          print "Stars:", self.stars35       elif self.CurrentData == "description":36          print "Description:", self.description37       self.CurrentData = ""38 39    # 內容事件處理40    def characters(self, content):41       if self.CurrentData == "type":42          self.type = content43       elif self.CurrentData == "format":44          self.format = content45       elif self.CurrentData == "year":46          self.year = content47       elif self.CurrentData == "rating":48          self.rating = content49       elif self.CurrentData == "stars":50          self.stars = content51       elif self.CurrentData == "description":52          self.description = content53   54 if ( __name__ == "__main__"):55    56    # 創建一個 XMLReader57    parser = xml.sax.make_parser()58    # turn off namepsaces59    parser.setFeature(xml.sax.handler.feature_namespaces, 0)60 61    # 重寫 ContextHandler62    Handler = MovieHandler()63    parser.setContentHandler( Handler )64    65    parser.parse("movies.xml")

執行結果:

*****Movie*****Title: Enemy BehindType: War, ThrillerFormat: DVDYear: 2003Rating: PGStars: 10Description: Talk about a US-Japan war*****Movie*****Title: TransformersType: Anime, Science FictionFormat: DVDYear: 1989Rating: RStars: 8Description: A schientific fiction*****Movie*****Title: TrigunType: Anime, ActionFormat: DVDRating: PGStars: 10Description: Vash the Stampede!*****Movie*****Title: IshtarType: ComedyFormat: VHSRating: PGStars: 2Description: Viewable boredom

參考文章

SAX,功能強大的 API

python XML解析

推薦書籍

《Python Cookbook》第12章:XML處理

 


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 湖南省| 聂拉木县| 雷波县| 东辽县| 贵溪市| 栾城县| 玛曲县| 汕头市| 清新县| 大埔区| 探索| 邹平县| 江津市| 江油市| 金昌市| 华亭县| 垫江县| 尚义县| 察隅县| 永定县| 迁安市| 东至县| 稻城县| 恭城| 温州市| 桐柏县| 来凤县| 县级市| 晋城| 长岭县| 黄冈市| 新沂市| 沁水县| 尼木县| 东莞市| 合水县| 锦州市| 克什克腾旗| 黑河市| 颍上县| 泰州市|