Linux C操作XML文件


1 簡介

介紹使用C語言操作xml文件。

使用的開源庫:mxml

mxml源碼路徑:michaelrsweet/mxml: Tiny XML library. (github.com)

mxml官網:Mini-XML (msweet.org)

mxml官方API使用文檔:Mini-XML 3.2 API Reference (msweet.org)

2 安裝

提前說明:mxml編譯之后會生成一個靜態庫和動態鏈接庫。

首先下載源碼壓縮包:michaelrsweet/mxml: Tiny XML library. (github.com)

然后解壓之后,按照官方網站的說明進行執行。

  1. 配置編譯環境
./configure

配置之后,會檢查編譯環境和配置編譯生成的庫存放路徑,默認放在usr/local中。

如何需要指定庫存放路徑,可使用如下命令修改:

./configure --prefix=/foo

image-20210507181722591

2)編譯

直接運行:

make

image-20210507181828400

編譯完成之后會生成:libmxml.so.1.6、libmxml.a、testmxml(測試代碼)。

3)將mxml安裝到系統庫中

執行:

make install

image-20210507182211455

安裝之后,使用時包含mxml.h即可。

#include <mxml.h>

在編譯程序的使用,可使用 -lmxml 來鏈接mxml庫。

3 測試

使用源文件自帶的測試案例進行測試。

編譯testmxml.c:

gcc testmxml.c -lmxml -o testxml	

運行:

./testxml test.xml

如果運行出現以下錯誤,表示沒找到libmxml.so.1庫。

image-20210508101409374

原因:我使用的gcc編譯默認使用的是64位的庫,也就是/usr/lib64,但是這個庫中沒有libmxml.so.1

編譯的libmxml.so也是一個64位的庫:

$ file /usr/local/lib/libmxml.so.1.6 
/usr/local/lib/libmxml.so.1.6: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=4e488abf69cf58184b46a03b881e67a5a92c155f, not stripped

解決方式:建立一個軟連接,將安裝庫的路徑鏈接到系統庫中。

sudo ln -s /usr/local/lib/libmxml.so.1 /usr/lib64/libmxml.so.1

然后重新執行即可。

image-20210508101604090

4 部分函數介紹

首先先介紹一些基本信息。

4.1 節點

XML文件中的信息都存放在節點中,節點使用mxml_node_t數據結構進行定義,每個節點有個type成員(定義了節點的類型)、可選數據、父節點(parent 上)、子節點(child 下)、兄弟節點(prev 左和next右)。

struct _mxml_node_s			/**** An XML node. ****/
{
  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 */
};

舉例說明,有個xml文件格式如下:

<?xml version="1.0" encoding="utf-8"?>
<data>
    <node>val1</node>
    <node>val2</node>
    <node>val3</node>
    <group>
        <node>val4</node>
        <node>val5</node>
        <node>val6</node>
    </group>
    <node>val7</node>
    <node>val8</node>
</data>

則其在內存中的節點樹關系如下:

?xml version="1.0" encoding="utf-8"?
  |
data
  |
node - node - node - group - node - node
  |      |      |      |       |      |
val1   val2   val3     |     val7   val8
                       |
                     node - node - node
                       |      |      |
                     val4   val5   val6

”-“:表示兄弟節點;"|":指向第一個子節點。

4.1.1 節點類型

節點類型數據結構定義如下:

typedef enum mxml_type_e		/**** The XML node type. ****/
{
  MXML_IGNORE = -1,	/* Ignore/throw away node @since Mini-XML 2.3@ */
  MXML_ELEMENT,	/* XML element with attributes 節點帶屬性 */
  MXML_INTEGER,	/* Integer value 整型值 */
  MXML_OPAQUE,	/* Opaque string 不透明字符串,不進行字符串分割 */
  MXML_REAL,	/* Real value 實數 */
  MXML_TEXT,	/* Text fragment 文本片段 */
  MXML_CUSTOM	/* Custom data @since Mini-XML 2.1@ */
} mxml_type_t;

相關函數:獲取節點類型。

mxml_type_t mxmlGetType(mxml_node_t *node);

4.1.2 相關函數

獲取第一個子節點:

mxml_node_t *mxmlGetFirstChild(mxml_node_t *node);

獲取最后一個子節點:

mxml_node_t *mxmlGetLastChild(mxml_node_t *node);

獲取兄弟節點(next右):

mxml_node_t *mxmlGetNextSibling(mxml_node_t *node);

獲取兄弟節點(prev 左):

mxml_node_t *mxmlGetPrevSibling(mxml_node_t *node);

獲取父節點:

mxml_node_t *mxmlGetParent(mxml_node_t *node);

4.2 創建xml文件並保存

通過實例簡述一下如何創建一個XML文件,並保存它。

void creat_xml(void)
{
    mxml_node_t *xml;    /* <?xml ... ?> */
    mxml_node_t *data;   /* <data> */
    mxml_node_t *node;   /* <node> */
    mxml_node_t *group;  /* <group> */

    xml = mxmlNewXML("1.0");  //xml頭部

    data = mxmlNewElement(xml, "data");  //創建節點<data>,父節點為xml

        node = mxmlNewElement(data, "node");  //創建節點<note>,父節點為data
        mxmlNewText(node, 0, "val1");  //設置節點<note>的值
        node = mxmlNewElement(data, "node");
        mxmlNewText(node, 0, "val2");
        node = mxmlNewElement(data, "node");
        mxmlNewText(node, 0, "val3");

        group = mxmlNewElement(data, "group");

            node = mxmlNewElement(group, "node");
            mxmlNewText(node, 0, "val4");
            node = mxmlNewElement(group, "node");
            mxmlNewText(node, 0, "val5");
            node = mxmlNewElement(group, "node");
            mxmlNewText(node, 0, "val6");

        node = mxmlNewElement(data, "node");
        mxmlNewText(node, 1, "val7");
        node = mxmlNewElement(data, "node");
        mxmlNewText(node, 1, "val8");   

    //save xml
    FILE *fp;
    fp = fopen("filename.xml", "w");
    mxmlSaveFile(xml, stdout, MXML_NO_CALLBACK);
    fclose(fp);
}

對涉及的函數進行簡單介紹:

/*
 * brife: 新建一個新的XML文檔
 * para[in] version: Version number to use
 * return: 新XML文檔父節點
*/
mxml_node_t *mxmlNewXML(const char *version);
/*
 * brife: 創建一個新的節點
 * para[in] parent: 父節點
 * para[in] name: 創建節點名
 * return: 新節點
*/
mxml_node_t *mxmlNewElement(mxml_node_t *parent, const char *name);
/*
 * brife: 創建一個新的節點文本內容
 * para[in] parent: 父節點
 * para[in] whitespace: 1 = leading whitespace, 0 = no whitespace
 * para[in] string: 文本內容
 * return: 新節點
*/
mxml_node_t *mxmlNewText(mxml_node_t *parent, int whitespace, const char *string);
/*
 * brife: 保存一個xml樹到文件中
 * para[in] note: xml樹節點
 * para[in] fp: 寫入的文件流指針
 * para[in] cb: 空白回調函數,控制保存文件時插入的"空白"字符
 * return: 成功返回0,出錯返回-1
*/
int mxmlSaveFile(mxml_node_t *node, FILE *fp, mxml_save_cb_t cb);


免責聲明!

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



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