我對現在的解析html的算法還是比較滿意的。現階段,經過我的一些測試,添加了對BR,IUPUT,IMG,META,SCRIPT,注釋等特殊html語法的支持。對於完全符合html語法規范的頁面,效果是令人滿意的。不足之處是缺乏對錯誤的包容能力,對不符合html語法的頁面可能解析出錯或者異常。如果要把它做成完善的html解析器,我認為必須實現一個優先級算法,提供錯誤的包容能力。不過我想,這個問題相當復雜,暫時不能很好的解決。現在,我決定采取另外一種折中的方式,即只解析自定義的控件,而不處理普通的html控件。以現在的算法,可以很輕易的實現這個功能。
個人覺得,使用用戶控件,然後在控件輸出的時候截獲render應該是可取的。但個人感覺這種方式實際使用負載,不夠靈活。我個人更傾向於實現一個輕量級的、易控的靜態頁面生成類庫,可以輕松自由的進行自定義和擴展。對於大多數網站來說,首頁和分類頁面的請求都是很頻繁的,並且內容也需要經常性的更新,使用Asp.Net的緩存機制是一個很好的選擇;但是對於網站的內容頁,如新聞或者軟件下載的內容頁面,相對來說請求頻率要低得多,動態生成或者使用緩存都是不合適的。這種情況最好的選擇是生成靜態頁面,然後保存在硬盤上。另外,對於實時性要求不高的首頁或者分類頁,也可以結合shtml的include機制,將內容部分用模板的方式靜態生成保存在硬盤上。
正如本文開頭所說,由於聯系暑期實習單位的事情,最近幾天都暫停開發了。在這裡我還是先將上一篇文章沒說完的繼續說完。
整個解析模塊主要由三個類來構成:StaticControlFactory、ParseStatusManager和StaticBaseControl構成的。其中StaticControlFactory主要負責對模板進行字符分析處理和控件的處理;ParseStatusManager主要負責對控件解析狀態進行處理,以及對StaticControlFactory發出處理命令;StaticBaseControl是實體類,保存相關結果。
代碼結構自認為還是很清晰的,並且有很多注釋,我就不詳細解釋了,主要說明幾個關鍵的地方。StaticControlFactory中使用了堆棧來保存控件的層次結構。每當創建了新的控件,就將新控件加入到當前控件的子控件集合中,然後將當前控件推入堆棧,新控件成為當前控件。當新控件解析完畢後則反向操作。ParseStatusManager的狀態管理也采用了相似的方式,只是沒有前者的層次結構。每次StaticControlFactory讀取到邊界字符時,就調用ParseStatusManager對象的ChangeStatus方法,實現相應的狀態轉化。ParseStatusManager對StaticControlFactory的操作,我使用了代理結合Command模式的方式來實現。這種方式最大的好處是ParseStatusManager不需要維護StaticControlFactory的一大堆方法簽名,只需要傳入合適的命令就可以了。如果需要在處理狀態轉換的時候,需要增加新的處理,只需要使StaticControlFactory增加對一個新的命令的支持就可以了。
為了增加對不符合<flag name=value>body</flag>形式的標簽,包括img、br之類可以無結尾或使用/>簡短結束標志的標簽的支持,對StaticControlFactory增加了幾個方法,ReadNextWord用以獲取控件開始標簽後的下一個單詞,以判斷當前標簽是否是定義的特殊標簽,ProcessForScriptBlock用以專門處理Script模塊。如果希望將類庫改成指處理我們定義的特殊標簽,就可以在每次讀到控件開始標記的時候使用ReadNextWord讀取控件類型,在判斷正確後才開始控件的解析操作;對每次讀到控件結束標記時也進行相似操作。
現在的方案實際上是我的第二個方案。第一個方案使用了遞歸,思路不是很清晰,調試起來相當麻煩,現在的方案要清晰多了。對於數據綁定,在我的第一個方案裡已經部分實現了,主要采用了遍歷加反射的方式。遺憾的是還只支持了對對象數組這種數據源的支持,主要原因是我現在的項目使用了petshop3的結構,以數據實體的方式傳遞數據,並且沒有實現repeate之類控件嵌套形式下的綁定。不過預計這兩個問題都比較簡單,可以比較快的實現。我會盡快實現一個可使用的版本發布出來。
博客:http://homer.cnblogs.com/