最近做嵌入式開發,板子上面需要有解析XML的功能,理所當然地我就去網上找開源的來用。結果找來的要不是C++的,要不就是超級複雜的。像libxml,我統計了下解析一個40幾KB的XML檔案,居然動態申請記憶體100多次,對於沒有mmu功能的arm7,真是無福消受了。
所以,我只能自己寫一個來用了。
我寫的這個xml解析器,非常簡單,核心代碼只有600多行。當然,功能也相對弱些,只支援ansi編碼的xml檔案,只能解析,不能產生。
整個解析器只用到了 若干條 EBNF文法 和 一個DFA狀態機器 (用來跳過注釋的), 採用了遞迴下降的分析方法.
整個解析過程沒有動態申請記憶體,不會造成記憶體片段(特別適應於沒有mmu的裝置), 當然,在開始解析之前,還是需要提供一片緩衝給解析器用的,最後產生的XML樹,就放在這片緩衝裡面.
介面如下:
/******************************************************
/* minixml.h
/*
/* author:@#$%^&*
/*
/* about:
/* 該檔案提供根據解析XML檔案功能
/*
/*
/* sample:
/*
/* 支援平台: windows , linux 2.4,2.6 uclinux
/* [in] 表示是輸入參數
/* [out] 表示是輸出參數
/******************************************************/
#ifndef _MINIXML_H_08_17_
#define _MINIXML_H_08_17_
#define _CRT_SECURE_NO_DEPRECATE
#if defined (__cplusplus) || defined (c_plusplus)
extern "C" {
#endif
struct _MINI_XML_ATTRI;
struct _MINI_XML_NODE;
/* 記錄一個屬性資訊 */
typedef struct _MINI_XML_ATTRI
{
char* name; /* 屬性名稱 */
char* value; /* 屬性值 */
struct _MINI_XML_ATTRI* next; /* 指向下一個屬性 */
} MINI_XML_ATTRI;
/* 記錄一個XML節點資訊 */
typedef struct _MINI_XML_NODE
{
char* name; /* 節點名 */
char* value; /* 節點值 */
MINI_XML_ATTRI* attri_list; /* 屬性列表 */
struct _MINI_XML_NODE* parent; /* 父節點 */
struct _MINI_XML_NODE* child; /* 子節點, 若沒有則為空白 */
struct _MINI_XML_NODE* next; /* 同層下一節點 */
} MINI_XML_NODE;
////////////////////////////////////////////////////
/// 說明 : 解析XML檔案,返回XML的根節點
/// 參數 :
/// : xml xml檔案路徑 [in]
/// : buffer 供解析用的緩衝 [in]
/// : buffer_len 緩衝大小(單位:位元組) [in]
/// : error_reason 執行出錯時儲存錯誤原因 [in]
/// : root XML的根節點 [out]
/// 返回 : 成功 返回0 ,失敗返回 -1
/// 說明 :
/// : 問 :供解析用的緩衝應該取多大比較合適呢?
/// : 答 :供解析用的緩衝主要用來存放XML樹, 所以 buffer_len >= (XML檔案的大小) * 2 即可
/// :
int mini_parse_xml (char* xml,
char* buffer, int buffer_len,
char error_reason[128],
MINI_XML_NODE** root);
////////////////////////////////////////////////////
/// 說明 : 尋找特定節點的子節點
/// 參數 :
/// : father 父結點 [in]
/// : name 子孩子節點名 [in]
/// : child 子節點 [out]
int mini_find_child (MINI_XML_NODE* father, char* name, MINI_XML_NODE** child);
////////////////////////////////////////////////////
/// 說明 : 尋找特定節點的屬性值
/// 參數 :
/// : node 節點 [in]
/// : name 屬性名稱 [in]
/// : value 屬性值 [out]
int mini_find_attribute (MINI_XML_NODE* node, char* name, char** value);
////////////////////////////////////////////////////
/// 說明 : 列印XML樹,供調試用
int mini_print_tree (MINI_XML_NODE* root , int layer);
#if defined (__cplusplus) || defined (c_plusplus)
}
#endif
#endif