首先我得承認我喜歡電腦標準。假如每個人都遵從這個行業的標準,互連網將會是一個更好的媒體。使用標準化的資料交換格式才能使開放的和獨立於平台的計算模式切實可行。這就是我作為XML愛好者的原因。
幸運的是,我最喜愛的指令碼語言不但支援XML而且對其支援正不斷加強。PHP可以讓我迅速將XML文檔發布到互連網上,收集XML文檔的統計資訊,將XML文檔轉換成其它格式。例如,我時常用PHP的XML處理能力來治理我用XML所寫的文章和書。
本文中,我將討論任何用PHP內建的Expat解析器來處理XML文檔。通過範例,我將示範Expat的處理方法。同時,範例可以告訴你如何:
建立你自己的處理函數
將XML文檔轉換成你自己的PHP資料結構
介紹Expat
XML的解析器,同樣稱為XML處理器,可以使程式訪問XML文檔的結構和內容。Expat是PHP指令碼語言的XML解析器。它同時也運用在其它項目中,例如Mozilla、Apache和Perl。
什麼是基於事件的解析器?
XML解析器的兩種基本類型:
基於樹型的解析器:將XML文檔轉換成樹型結構。這類解析器分析整篇文章,同時提供一個API來訪問所產生樹的每個元素。其通用的標準為DOM(文檔對象模式)。
基於事件的解析器:將XML文檔視為一系列的事件。當一個非凡事件發生時,解析器將調用開發人員提供的函數來處理。
基於事件的解析器有一個XML文檔的資料集中視圖,也就是說它集中在XML文檔的資料部分,而不是其結構。這些解析器從頭到尾處理文檔,並將類似於-元素的開始、元素的結尾、特徵資料的開始等等-事件通過回調(callback)函數報告給應用程式。以下是一個"Hello-World"的XML文檔範例:
<greeting>
Hello World
</greeting>
基於事件的解析器將報告為三個事件:
開始元素:greeting
CDATA項的開始,值為:Hello World
結束元素:greeting
不像基於樹型的解析器,基於事件的解析器不產生描述文檔的結構。在CDATA項中,基於事件的解析器不會讓你得到父元素greeting的資訊。
然而,它提供一個更底層的訪問,這就使得可以更好地利用資源和更快地訪問。通過這種方式,就沒有必要將整個文檔放入記憶體;而事實上,整個文檔甚至可以大於實際記憶體值。
Expat就是這樣的一種基於事件的解析器。當然假如使用Expat,必要時它一樣可以在PHP中產生完全的原生樹結構。
上面Hello-World的範例包括完整的XML格式。但它是無效的,因為既沒有DTD(文件類型定義)與其聯絡,也沒有內嵌DTD。
對於Expat,這並沒有區別:Expat是一個不檢查有效性的解析器,因此忽略任何與文檔聯絡的DTD。但應注重的是文檔仍然需要完整的格式,否則Expat(和其他符合XML標準的解析器一樣)將會隨著出錯資訊而停止。
作為不檢查有效性的解析器,Exapt的快速性和輕便性使其十分適合互連網程式。
編譯Expat
Expat可以編譯進PHP3.0.6版本(或以上)中。從Apache1.3.9開始,Expat已經作為Apache的一部分。在Unix系統中,通過-with-xml選項配置PHP,你可以將其編譯入PHP。
假如你將PHP編譯為Apache的模組,而Expat將預設作為Apache的一部分。在Windows中,你則必須要載入XML動態串連庫。
XML範例:XMLstats
瞭解Expat的函數的一個辦法就是通過範例。我們所要討論的範例是使用Expat來收集XML文檔的統計資料。
對於文檔中每個元素,以下資訊都將被輸出:
該元素在文檔中使用的次數
該元素中字元資料的數量
元素的父元素
元素的子項目
注重:為了示範,我們利用PHP來產生一個結構來儲存元素的父元素和子項目
預備
用於產生XML解析器執行個體的函數為xml_parser_create()。該執行個體將用於以後的所有函數。這個思路非常類似於PHP中MySQL函數的串連標記。在解析文檔前,基於事件的解析器通常要求你註冊回呼函數-用於特定的事件發生時調用。Expat沒有例外事件,它定義了如下七個可能事件:
對象 XML解析函數 描述
元素 xml_set_element_handler() 元素的開始和結束
字元資料 xml_set_character_data_handler() 字元資料的開始
外部實體 xml_set_external_entity_ref_handler() 外部實體出現
未解析外部實體 xml_set_unparsed_entity_decl_handler() 未解析的外部實體出現