Duilib源碼分析(三)XML解析器—CMarkup


  上一節介紹了控件構造器CDialogBuilder,接下來將分析其XML解析器CMarkup;

  CMarkup:xml解析器,目前內置支持三種編碼格式:UTF8、UNICODE、ASNI,默認為UTF8;CMarkupNode:xml節點類

  先介紹CMarkup:

  XMLELEMENT: xml節點元素類型定義,iStart,節點元素在xml文件中的起始位置;iChild,節點元素子節點;iNext,節點元素的下一個節點(兄弟節點);iParent,節點元素的父節點;iData,

  節點元素的數據(事實上,這些值均為ULONG類似,即unsigned long;存儲的值為當前數據在內存緩沖區m_pstrXML中指向的位置)。

  CMarkupNode作為CMarkup的友元類,意味着可以訪問CMarkup的各成員函數和數據屬性,事實上后期的遍歷xml就是結合CMarkupNode的GetSibling和GetChild實現的。

  類成員數據:

    m_pstrXML:為CMarkup存儲的以加載xml文件數據內容的指針緩沖區;

    m_pElements:保存XMLELEMENT類型的節點元素信息的緩沖區,事實上可能有部分未預料的存儲空間;

    m_nElements:實際的保存m_pElements中有效的節點元素數;

    m_nReservedElements:預留的m_pElements緩沖區空間大小,具體策略為:m_nElements >= m_nReservedElements ) {m_nReservedElements += (m_nReservedElements / 2)

                 + 500;m_pElements = static_cast<XMLELEMENT*>(realloc(m_pElements, m_nReservedElements * sizeof(XMLELEMENT)));

    m_szErrorMsg:最近一次解析時的錯誤信息;

    m_szErrorXML:最近一次解析時的xml位置信息;

    m_bPreserveWhitespace:是否跳過忽略空格,默認是忽略;

  類成員函數:

    Load:通過參數pstrXML,傳入xml文件內容的方式解析,內部主要是分配m_pstrXML緩沖區並拷貝pstrXML內容,后通過_Parse解析;

    LoadFromMem:通過加載內存資源方式解析,內部通過宏處理時限寬字節unicode和多字節編譯時定義處理解析,最終也是分配m_pstrXML緩沖區並拷貝該內存數據內容,后通過_Parse解析;

    LoadFromFile:通過參數pstrFilename文件路徑名,可以是xml文件或是壓縮文件(內部為xml文件),對於xml文件或是壓縮文件處理讀取內部數據至臨時內存緩沖區中(解壓縮采用的是ZIP_INFO

    的cpp實現方式便於接口調用,參見duilib目錄文件XUnzip.cpp)並再次通過調用LoadFromMem加載解析;

    Release:主要用以釋放m_pstrXML和m_pElements緩沖區資源;

    IsValid:當前解析是否有效,通過m_pElements != NULL判斷;

    SetPreserveWhitespace:設置m_bPreserveWhitespace是否忽略解析中字符串的空格,

    GetLastErrorMessage:獲取m_szErrorMsg的最近一次解析時的錯誤信息;

    GetLastErrorLocation:獲取m_szErrorXML的最近一次解析時的xml位置信息;

    GetRoot:獲取根節點CMarkupNode,CMarkupNode(this, 1),以當前為第一個節點的節點對象;

    _ReserveElement:分配足夠的預留空間;

    _Parse:分配預留空間、初始化m_szErrorMsg、m_szErrorXML,並調用重載函數_Parse,執行真正的解析過程;

    _SkipWhitespace:重載版本均處理、跳過字符串空格;

    _SkipIdentifier:重載版本均均處理、跳過標志符號如:‘_’, ‘:’ ;

    _ParseData:解析元素屬性中數據;

    _ParseMetaChar:解析元字符,如:'&', '<','>','\"','\'','&'與'a', 'm', 'p', 't', ';'等相關組合字符串;

    _ParseAttributes:解析元素屬性;

    _Failed:保存解析中產生最近一次的錯誤信息、位置,m_szErrorMsg、m_szErrorXML;

  接下來CMarkupNode:

  XMLATTRIBUTE:節點屬性結構體定義,iName為屬性名,iValue為屬性值均為ULONG類型;

  MAX_XML_ATTRIBUTES:節點支持最多64個屬性個數;

  類成員數據:

    m_aAttributes:節點屬性列表(節點屬性數組,保存數據類似於鍵值對的方式);

    m_iPos:指定該屬性節點在所屬擁有者(指CMarkup對象)中的節點元素中的當前位置(事實上其節點元素也為指針數組保存);

    m_nAttributes:節點中屬性數;

    m_pOwner:該節點所屬擁有者(指CMarkup對象);

  類成員函數:

    CMarkupNode:重載版構造函數,其中一個以CMarkup對象和當前所屬節點所在位置初始化m_iPos;

    IsValid:當前節點是否有效,其通過m_pOwner != NULL判斷;

    GetParent:獲取當前節點的父節點node,事實上是通過創建一個CMarkupNode(m_pOwner, iPos),作為其父節點,iPos為當前節點的iParent值;

    GetSibling:獲取當前節點的下一個節點(兄弟節點),同GetParent一樣,iPos為當前節點的iNext值;

    GetChild:獲取當前節點的子節點,iPos為當前節點的iChild值;另外重載版本GetChild,參數為pstrName,遍歷當前節點所有子節點與pstrName匹配的節點;

    HasSiblings:是否有兄弟節點;

    HasChildren:是否有子節點;

    GetName:獲取當前節點名字;

    GetValue:獲取當前節點值;

    HasAttributes:當前節點是否有屬性,通過m_nAttributes > 0判斷;其重載版本HasAttribute,參數pstrName,判斷遍歷當前節點的所有屬性有與pstrName匹配的;

    GetAttributeCount:同HasAttributes,通過m_nAttributes判斷;

    GetAttributeName:獲取屬性名,參數iIndex為指定的屬性索引;

    GetAttributeValue:獲取屬性值,有四個重載版本,其中一個版本為參數iIndex,屬性索引;一個版本pstrName參數為屬性名;另外兩個版本差不多,只是返回值以輸入輸出參;

    _MapAttributes:最為核心的屬性映射處理函數,內部主要遍歷解析當前節點中各屬性及值,並存入m_aAttributes中並更新m_nAttributes值;

   最后說明:

    1. 從代碼中可以看出,CMarkup存儲了一份整個文件的內容,另外也保存了各個元素節點,並未對各個元素節點的屬性單獨存儲,即並未存儲CMarkupNode;

     此外在源碼中可以看出很多操作都會執行_MapAttributes,好在該遍歷映射不會很大,控制在最多64個屬性;

    2. 加載zip壓縮資源文件時,可以使用CachedResourceZip緩存資源,也可以直接使用的是ZIP-INFO的CPP版本(一個文件),使用到被宏重定義的接口:OpenZip、FindZipItem、UnzipItem、

     CloseZip;具體使用可參考XUnzip.cpp接口;默認使用的是OpenZip加載壓縮資源文件。

  還記得源碼分析(一)一節中,HandleMessage處理函數中消息WM_CRAETE處理過程嗎?

    1. CDialogBuilder構建各控件對象並形成控件樹,並返回第一個控件對象pRoot;

    2. m_pm.AttachDialog(pRoot);m_pm.AddNotifier(this);將控件attach到CPaintManagerUI  m_pm中管理,此外INotifyUI子類對象被加入到m_pm;這樣m_pm不僅管理控件對象

     也對消息監聽接口Notify回調,這樣用戶可以在Notify中實現自己的感興趣的消息映射處理,其Notify(TNotifyUI& msg)中的參數為通告消息msg;

  事實上我們主要需要弄清楚三點:一是如何繪制、二是數據如何處理、三是消息如何流轉;接下來下一節將對控件繪制和消息流轉進行分析。

  

    

    

    

    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM