C++ FFLIB之FFXML: 極簡化TinyXml 讀取

來源:互聯網
上載者:User

摘要:

XML是結構化的標記語言,經常被用來做設定檔。由於XML的具有非常強的自描述屬性,使用XML的設定檔往往直觀易懂。C++中解析XML已經有一些非常成熟的類庫可以使用,TinyXml是最受歡迎的解析類庫之一。儘管TinyXml已經已經封裝瞭解析細節,但是解析、遍曆Xml仍然是稍顯繁瑣。FFXML針對如下需求對TinyXml做了輕量封裝:

  • 只把XML當成設定檔,也就是說,只有對XML的讀取操作,在我日工作中,都是用XML當做純設定檔,把XML當成序列化檔案或資料檔案的情況少之又少。
  • XML設定檔不會太大,我們假設限制在幾千行以內,通常XML設定檔不需要那麼大,在這種需求下,的XML的讀取效率不是問題,易用性會被放到首位,必須非常容易擷取xml中的內容。
  • 我們知道XML是結構化的,有層級的概念,這對於C++中的記憶體模型多多少少會有區別,所以往往擷取XML內容的代碼會有各種迴圈、判斷、嵌套。FFXML提供了一種“標記文法”使得擷取XML內容可以和XML的結構息息對應,即保障了直觀,又很容易修改,比如調整了XML的層級關係,FFXML能夠保障大多數情況只需改幾個字母,而不是修改嵌套的迴圈代碼.

標記語言:

實現先給出樣本的XML內容

<game type = "good">    <scene>happly</scene>    <role ID="123456"  pos = "any">        <name nick = "xx" >OhNice</name>        <num>99</num>    </role></game>

 我們知道,如果使用tinyXml讀取XML,每一層都需要使用特定的介面擷取,從而必須要寫一寫迴圈和判斷甚至嵌套。FFXML提供了一種“標記文法”來表示XML中各個層級的關係:

  • game.scene ffxml通過 “.”  來分割各個層級,game.scene 代表擷取root標記下層的scene標記  在FFXML中擷取scen標記的值簡單到一行代碼const char* scene_val = ffxml.get(“game.scene”);
  • game.{type}  FFXML通過 “{}”表示屬性標記,root.{type}表示擷取root標記內的type屬性的值, 使用FFXML擷取type屬性的值的代碼仍然只有一行:const char* type_val = ffxml.get(“game.{type}”);
  • game.@0  擷取game標籤下的索引0的標籤內容,也就是scene的內容,即const char* scene_val = ffxml.get(“game.@0”);
  • game.&0  擷取game標記下索引0的字標記的name,也就是ffxml.get(“game.&0”) == “scene”;
  • game.{@0} 擷取game標記下索引0的屬性值
  • game.{&0}  擷取game標記下索引0的屬性的name
  • FFXML 提供size介面擷取字標記的數量如ffxml.size(“game.role”)   表示role標記下字子標記的數量=2
  • size 介面也可以擷取屬性的數量,如ffxml.size(“game.role.{}”) 表示role標記屬性的個個數

 範例程式碼:

 

#include "xml/ffxml.h"using namespace ff;int main(int argc, char* argv[]){    ffxml_t ffxml;        //! 載入test.xml    if (ffxml.load("test.xml"))    {        printf("test.xml 載入失敗\n");        return 1;    }    printf("擷取欄位     game.scene:        %s\n", ffxml.get("game.scene"));    printf("擷取欄位     game.role.name:    %s\n", ffxml.get("game.role.name"));    printf("擷取欄位     game.role.num:     %s\n", ffxml.get("game.role.num"));        printf("擷取屬性     game.{type}:       %s\n", ffxml.get("game.{type}"));    printf("擷取屬性     game.role.{ID}:    %s\n", ffxml.get("game.role.{ID}"));        printf("擷取標記數量 game:              %u\n", ffxml.size("game"));    printf("擷取標記數量 game.role:         %u\n", ffxml.size("game.role"));        printf("擷取屬性數量 game:              %u\n", ffxml.size("game.{}"));    printf("擷取屬性數量 game.role:         %u\n", ffxml.size("game.role.{}"));        //! 遍曆子節點    char arg_key[128];    char arg_val[128];    for (size_t i = 0; i < ffxml.size("game.role"); ++i)    {        sprintf(arg_key, "game.role.&%u", i);        sprintf(arg_val, "game.role.@%u", i);        printf("遍曆子節點   game.role:         %s->%s\n", ffxml.get(arg_key), ffxml.get(arg_val));    }        //! 遍曆屬性節點    for (size_t i = 0; i < ffxml.size("game.role"); ++i)    {        sprintf(arg_key, "game.role.{&%u}", i);        sprintf(arg_val, "game.role.{@%u}", i);        printf("遍曆屬性     game.role:         %s->%s\n", ffxml.get(arg_key), ffxml.get(arg_val));    }            printf("組合         game.role.@1.{@nick} %s\n", ffxml.get("game.role.@0.{@nick}"));    return 0;}

總結:

詳細原始碼:https://github.com/fanchy/fflib

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.