libmxml數據結構(源碼分析)

来源:https://www.cnblogs.com/kingstarer/archive/2019/04/05/10659709.html
-Advertisement-
Play Games

libmxml是一個開源、小巧的C語言xml庫。這裡簡單分析一下它是用什麼樣的數據結構來保存分析過的xml文檔。 mxml關鍵的結構體mxml_node_t是這樣的實現的: 它使用左孩子右兄弟的樹形結構來描述xml報文:即下層節點登記在child鏈表,兄弟節點登記在next鏈表。 如果某個節點下麵有 ...


  libmxml是一個開源、小巧的C語言xml庫。這裡簡單分析一下它是用什麼樣的數據結構來保存分析過的xml文檔。

  mxml關鍵的結構體mxml_node_t是這樣的實現的:

struct mxml_node_s            /**** An XML node. @private@ ****/
{
  mxml_type_t        type;        /* Node type */
  struct mxml_node_s    *next;        /* Next node under same parent */
  struct mxml_node_s    *prev;        /* Previous node under same parent */
  struct mxml_node_s    *parent;    /* Parent node */
  struct mxml_node_s    *child;        /* First child node */
  struct mxml_node_s    *last_child;    /* Last child node */
  mxml_value_t        value;        /* Node value */
  int            ref_count;    /* Use count */
  void            *user_data;    /* User data */
};

typedef struct mxml_node_s mxml_node_t;    /**** An XML node. ****/

  

   它使用左孩子右兄弟的樹形結構來描述xml報文:即下層節點登記在child鏈表,兄弟節點登記在next鏈表。 如果某個節點下麵有N個子節點,則child指向第一個子節點,該子節點的next指向下一個同父節點的子節點。  比較特殊的是,mxml把xml節點值也認為是一個子節點。例如<group>value</group>, 其中value(type是MXML_OPAQUE)是一個獨立的子節點,掛載在group節點(type是MXML_ELEMENT)下麵。  另外,空白符(空格,回車換行,製表符)和註釋,雖然對xml報文無實質意義,但mxml還是把它們做為一個節點存儲起來。

  由於mxml只是使用簡單的鏈表存儲xml元素,所以元素節點個數比較多時,mxml查找元素效率是比較低的。所以libmxml提供了一個索引查找的函數,它需要先遍歷xml元素樹,生成一個排序過的數組,加快查找速度。

   為了方便大家理解,我寫了一個函數列印xml結構體。

 

void printNode(mxml_node_t *node, int nNodeSn, int level)
{
    static int currNodeSn = 0;
    if (node == NULL)
    {
        return;
    }

    ++currNodeSn; //每遇到一個新節點 則將節點序號遞增,做為本節點序號
    printf("[%- 3d -> %- 3d] ", currNodeSn, nNodeSn);

    switch (node->type)
    {
    case MXML_ELEMENT:
        {
            int i;
            printf("level %d MXML_ELEMENT [%s]", level, node->value.element.name);
            for (i = 0; i < node->value.element.num_attrs; ++i)
            {
                printf(" %s=%s", node->value.element.attrs[i].name, node->value.element.attrs[i].value);
            }
            printf("\n");
        }
        break;
    case MXML_INTEGER:
        printf("level %d MXML_INTEGER %d\n", level, node->value.integer);
        break;
    case MXML_OPAQUE:
        printf("level %d MXML_OPAQUE [%s]\n", level, node->value.opaque);
        break;
    case MXML_REAL:
        printf("level %d MXML_REAL %lf\n", level, node->value.real);
        break;
    case MXML_TEXT:
        printf("level %d MXML_TEXT [%s]\n", level, node->value.text.string);
        break;
    case MXML_CUSTOM:
        printf("level %d MXML_CUSTOM\n", level);
        break;
    default:
        printf("unknown node type %d\n", node->type);
    }

    //深度優先遍歷
    if (node->child)
    {
        //訪問子節點時把本節點序號做為父節點序號 層級加1
        printNode(node->child, currNodeSn, level + 1);
    }

    if (node->next)
    {
        //訪問兄弟節點,直接傳父節點序號即可 層級也不用加1
        printNode(node->next, nNodeSn, level);
    }
}

  運行示例如下:

  xml源如下:

<?xml version="1.0" encoding="GBK" ?>
<group>
    <option>122334 我們
        <string>我們</string>45677
        <keyword type="opaque">InputSlot</keyword>
        <default type="opaque">Auto</default>
        <text>Media Source</text>
        <order type="real">10.000000</order>
        <choice>
            <keyword type="opaque">Auto</keyword>
            <text>Auto Tray Selection</text>
            <code type="opaque" />
        </choice>
        <choice>
            <keyword type="opaque">Upper</keyword>
            <text>Tray 1</text>
            <code type="opaque">&lt;&lt;/MediaPosition 0&gt;&gt;setpagedevice</code>
        </choice>
        <choice>
            <keyword type="opaque">Lower</keyword>
            <text>Tray 2</text>
            <code type="opaque">&lt;&lt;/MediaPosition 1&gt;&gt;setpagedevice</code>
        </choice>
    </option> 我 12334545 050504550
    <integer>123</integer>
    <string>Now is the time for all good men to come to the aid of their
country.</string>
    <!-- this is a comment -->
    <![CDATA[this is CDATA 0123456789ABCDEF]]>
</group>

  用我這個printNode分析結果如下:

說明:[ 1  ->  0 ],代表本節點序號是1,其父節點序號是0,level 0代表本節點是最頂層節點。

[ 1  ->  0 ] level 0 MXML_ELEMENT [?xml version="1.0" encoding="GBK" ?]
[ 2  ->  1 ] level 1 MXML_OPAQUE [
]
[ 3  ->  1 ] level 1 MXML_ELEMENT [group]
[ 4  ->  3 ] level 2 MXML_OPAQUE [
        ]
[ 5  ->  3 ] level 2 MXML_ELEMENT [option]
[ 6  ->  5 ] level 3 MXML_OPAQUE [122334 我們
                ]
[ 7  ->  5 ] level 3 MXML_ELEMENT [string]
[ 8  ->  7 ] level 4 MXML_OPAQUE [我們]
[ 9  ->  5 ] level 3 MXML_OPAQUE [45677
                ]
[ 10 ->  5 ] level 3 MXML_ELEMENT [keyword] type=opaque
[ 11 ->  10] level 4 MXML_OPAQUE [InputSlot]
[ 12 ->  5 ] level 3 MXML_OPAQUE [
                ]
[ 13 ->  5 ] level 3 MXML_ELEMENT [default] type=opaque
[ 14 ->  13] level 4 MXML_OPAQUE [Auto]
[ 15 ->  5 ] level 3 MXML_OPAQUE [
                ]
[ 16 ->  5 ] level 3 MXML_ELEMENT [text]
[ 17 ->  16] level 4 MXML_OPAQUE [Media Source]
[ 18 ->  5 ] level 3 MXML_OPAQUE [
                ]
[ 19 ->  5 ] level 3 MXML_ELEMENT [order] type=real
[ 20 ->  19] level 4 MXML_OPAQUE [10.000000]
[ 21 ->  5 ] level 3 MXML_OPAQUE [
                ]
[ 22 ->  5 ] level 3 MXML_ELEMENT [choice]
[ 23 ->  22] level 4 MXML_OPAQUE [
                        ]
[ 24 ->  22] level 4 MXML_ELEMENT [keyword] type=opaque
[ 25 ->  24] level 5 MXML_OPAQUE [Auto]
[ 26 ->  22] level 4 MXML_OPAQUE [
                        ]
[ 27 ->  22] level 4 MXML_ELEMENT [text]
[ 28 ->  27] level 5 MXML_OPAQUE [Auto Tray Selection]
[ 29 ->  22] level 4 MXML_OPAQUE [
                        ]
[ 30 ->  22] level 4 MXML_ELEMENT [code] type=opaque
[ 31 ->  22] level 4 MXML_OPAQUE [
                ]
[ 32 ->  5 ] level 3 MXML_OPAQUE [
                ]
[ 33 ->  5 ] level 3 MXML_ELEMENT [choice]
[ 34 ->  33] level 4 MXML_OPAQUE [
                        ]
[ 35 ->  33] level 4 MXML_ELEMENT [keyword] type=opaque
[ 36 ->  35] level 5 MXML_OPAQUE [Upper]
[ 37 ->  33] level 4 MXML_OPAQUE [
                        ]
[ 38 ->  33] level 4 MXML_ELEMENT [text]
[ 39 ->  38] level 5 MXML_OPAQUE [Tray 1]
[ 40 ->  33] level 4 MXML_OPAQUE [
                        ]
[ 41 ->  33] level 4 MXML_ELEMENT [code] type=opaque
[ 42 ->  41] level 5 MXML_OPAQUE [<</MediaPosition 0>>setpagedevice]
[ 43 ->  33] level 4 MXML_OPAQUE [
                ]
[ 44 ->  5 ] level 3 MXML_OPAQUE [
                ]
[ 45 ->  5 ] level 3 MXML_ELEMENT [choice]
[ 46 ->  45] level 4 MXML_OPAQUE [
                        ]
[ 47 ->  45] level 4 MXML_ELEMENT [keyword] type=opaque
[ 48 ->  47] level 5 MXML_OPAQUE [Lower]
[ 49 ->  45] level 4 MXML_OPAQUE [
                        ]
[ 50 ->  45] level 4 MXML_ELEMENT [text]
[ 51 ->  50] level 5 MXML_OPAQUE [Tray 2]
[ 52 ->  45] level 4 MXML_OPAQUE [
                        ]
[ 53 ->  45] level 4 MXML_ELEMENT [code] type=opaque
[ 54 ->  53] level 5 MXML_OPAQUE [<</MediaPosition 1>>setpagedevice]
[ 55 ->  45] level 4 MXML_OPAQUE [
                ]
[ 56 ->  5 ] level 3 MXML_OPAQUE [
        ]
[ 57 ->  3 ] level 2 MXML_OPAQUE [ 我12334545 050504550
        ]
[ 58 ->  3 ] level 2 MXML_ELEMENT [integer]
[ 59 ->  58] level 3 MXML_OPAQUE [123]
[ 60 ->  3 ] level 2 MXML_OPAQUE [
        ]
[ 61 ->  3 ] level 2 MXML_ELEMENT [string]
[ 62 ->  61] level 3 MXML_OPAQUE [Now is the time for all good men to come to the aid of their
country.]
[ 63 ->  3 ] level 2 MXML_OPAQUE [
        ]
[ 64 ->  3 ] level 2 MXML_ELEMENT [!-- this is a comment --]
[ 65 ->  3 ] level 2 MXML_OPAQUE [
        ]
[ 66 ->  3 ] level 2 MXML_ELEMENT [![CDATA[this is CDATA 0123456789ABCDEF]]]
[ 67 ->  3 ] level 2 MXML_OPAQUE [
]

 

   


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • (1) plot是標準的繪圖庫,調用函數plot(x,y)就可以創建一個帶有繪圖的圖形視窗(其中y是x的函數)。輸入的參數為具有相同長度的數組(或列表);或者plot(y)是plot(range(len(y)),y)的簡寫。 例1:python實現使用200個採樣點來繪製sin(x),並且每隔四個點 ...
  • 一、元組tuple 1、作用 存多個值,對比列表來說,元組不可變,主要是用來讀。 2、定義 與列表類型比,只不過[ ]換成() 3、常用操作 4、元組案列 二、字典dict 特別瞭解:dict是python中僅存的mapping類型 1、作用 存多個值,key-value存取,取值速度快。 2、定義 ...
  • 一,本機配置 Win10 64bit NVIDIA GeForce GTX 960M Python3.7(Anaconda) 二,安裝CUDA 親測,TensorFlow-gpu1.13.1支持cuda10.0的版本,所以我們可直接選擇cuda10.0的版本 Window10下載CUDA10 安裝步 ...
  • PHP原生寫的生成圖片縮略圖類,本文以京東商品圖片為例,分別生成三種不同尺寸的圖片。調用方法很簡單隻要傳參數高度和寬度,及新圖片的名稱。 引入縮略圖類 生成三個不同尺寸縮略圖 本實例下載:https://www.sucaihuo.com/php/867.html ...
  • John and Mary want to travel between a few towns A, B, C ... Mary has on a sheet of paper a list of distances between these towns. ls = [50, 55, 57, 5 ...
  • 1.變數的作用域和靜態變數 函數的參數以及參數的引用傳遞 函數的返回值以及引用返回 外部文件的導入 系統內置函數的考察 變數的作用域也稱為變數的範圍,變數的範圍即他定義上下文的背景(也是它生效的範圍)。大部分php變數只有一生效的範圍,這個單獨的範圍也包括include 和require 引入的文件 ...
  • 矩陣快速冪 設答案為f(i) 舉個例子: 當i==2時,包含0的值有:10,20,30,40,50,60,70,80,90,100;0的個數為11,f(2)=11; i==3時;可以從i==2的情況遞推, 第一步:i==2時的數據範圍:1-100;在這100個數後面補0;補0後,這些數在1-1000 ...
  • 一、可變與不可變類型 二、數字類型 1、用途 2、定義方式 3、總結 三、字元串類型 1、作用 2、定義方式 3、常用操作+內置方法 # 優先掌握的操作: 4、總結 四、列表類型 1、用途 2、定義方式 3、常用操作+內置的方法 4、總結 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...