欢迎小伙伴的点评✨✨,相互学习、博主将自己研发xml微型服务器的经验与之分享🌏🌏🙂
文章目录
- 前言
- 一、使用mxml库编写Xml文件
- 1.1 经典实例Demo_1
- 1.2、经典实例Demo_2
- 1.3、经典实例Demo_3
- 二、总结
前言
本章将会给大家带来mini-xml的基本实例解析
一、使用mxml库编写Xml文件
mxml 环境配置
1.1 经典实例Demo_1
#include "config.h"
#include "mxml.h"
#include "mxml-private.h"
int main()
{mxml_node_t *xml; /*定义根节点指针*/mxml_node_t *data; /*定义节点指针*/mxml_node_t *node; /*定义节点指针*/mxml_node_t *group; /*定义节点指针*/xml = mxmlNewXML("1.0"); /*设置xml版本号*/data = mxmlNewElement(xml, "data"); /*设置根节点data*/mxmlElementSetAttr(data,"type","val"); /*设置节点data的属性为val*/node = mxmlNewElement(data, "node"); /*基于根节点data的基础上新建节点node*/mxmlNewText(node, 0, "val1"); /*设置当前节点node的文本为val1*/node = mxmlNewElement(data, "node"); /*基于根节点data的基础上新建节点node*/mxmlNewText(node, 0, "val2"); /*设置当前节点node的文本为val2*/node = mxmlNewElement(data, "node"); /*基于根节点data的基础上新建节点node*/mxmlNewText(node, 0, "val3"); /*设置当前节点node的文件为val3*/group = mxmlNewElement(data, "group"); /*基于根节点data的基础上新建节点group*/node = mxmlNewElement(group, "group_node"); /*基于节点group的基础上新建节点group_node*/mxmlNewText(node, 0, "val4"); /*设置当前节点group_node的文本为val4*/node = mxmlNewElement(group, "group_node"); /*基于节点group的基础上新建节点group_node*/mxmlNewText(node, 0, "val5"); /*设置当前节点group_node的文本为val5*/node = mxmlNewElement(group, "group_node"); /*基于节点group的基础上新建节点group_node*/mxmlNewText(node, 0, "val6"); /*设置当前节点group_node的文本为val6*/node = mxmlNewElement(data, "node"); /*基于根节点data的基础上新建节点node*/mxmlNewText(node, 0, "val7"); /*设置当前节点node的文本为val7*/node = mxmlNewElement(data, "node"); /*基于根节点data的基础上新建节点node*/mxmlNewText(node, 0, "val8"); /*设置当前节点node的文本为val8*/FILE *fp; /*新建文件流指针 fp*/fp = fopen("demo.xml","wb"); /*新建或者打开demo.xml*/mxmlSaveFile(xml,fp,MXML_NO_CALLBACK); /*将数据保存到文件*/fclose(fp); /*关闭文件流指针*/mxmlDelete(xml); /*关闭xml根节点*/return 0;
}
代码解析:
1、mxml_node_t :XML节点数据类型,其类型为typedef struct mxml_node_s mxml_node_t;
其中mxml_node_s 结构体成员如下:
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 */
};
2、mxmlNewXML:创建一个新的 XML 文档树,使用的版本号返回值。
其中mxmlNewXML()声明如下:
mxml_node_t *mxmlNewXML (const char *version);
参数
version:版本号
返回值:新的 “?xml” 节点
3、mxmlNewElement:创建一个新的 XML 元素节点
其中mxmlNewElement()声明如下:
mxml_node_t *mxmlNewElement (
mxml_node_t *parent,
const char *name
);
参数
parent:父节点或MXML_NO_PARENT
name:XML元素名称
返回值:新节点
4、mxmlNewText:创建新的文本分段节点
mxml_node_t *mxmlNewText (
mxml_node_t *parent,
int whitespace,
const char *string
);
参数
parent :父节点或 MXML_NO_PARENT ;
whitespace: 1 = 有前导空格, 0 = 没有空格;
string:字符串、返回值、新节点;
返回值:新节点
5、mxmlSaveFile:保存一个XML节点树到一个文件。
int mxmlSaveFile ( mxml_node_t *node, FILE *fp, mxml_save_cb_t cb
);
参数
node:准备要写入的节点;
fp:准备写入的文件;
cb :空白回调函数或者MXML_NO_CALLBACK;
编译后生成文件如下:
返回值:成功返回 0,错误返回 -1。
此时生成的xml的文件是没有排版格式,使用普通文本查看器不方便查看、可以使用mxmlSaveFile 中的第三个参数设置成回调函数。代码如下:
#include "config.h"
#include "mxml.h"
#include "mxml-private.h"const char *whitespace_cb(mxml_node_t *node,int where)
{const char *name;name = node->value.element.name; /*获取当前节点的名字*/if (!strcmp(name, "data")) /*判断当前节点的名字是否为data*/{if (where == MXML_WS_BEFORE_OPEN) /*如果name == "data",则在节点<data>前加入回车*/{return ("\n");}else if(where == MXML_WS_BEFORE_CLOSE) /*如果name == "data",则在节点</data>前加入回车*/{ return ("\n");} }else if (!strcmp(name, "node")) {if (where == MXML_WS_BEFORE_OPEN){return ("\n\t\t");}else if(where == MXML_WS_BEFORE_CLOSE){ } }else if(!strcmp(name, "group")){if (where == MXML_WS_BEFORE_OPEN){return ("\n\t\t");}else if(where == MXML_WS_BEFORE_CLOSE){ return ("\n\t\t");} }else if (!strcmp(name, "group_node")){if (where == MXML_WS_BEFORE_OPEN){return ("\n\t\t\t");}else if(where == MXML_WS_BEFORE_CLOSE){ }}return (NULL);
}int main()
{mxml_node_t *xml; /*定义根节点指针*/mxml_node_t *data; /*定义节点指针*/mxml_node_t *node; /*定义节点指针*/mxml_node_t *group; /*定义节点指针*/xml = mxmlNewXML("1.0"); /*设置xml版本号*/data = mxmlNewElement(xml, "data"); /*设置根节点data*/mxmlElementSetAttr(data,"type","val"); /*设置节点data的属性为val*/node = mxmlNewElement(data, "node"); /*基于根节点data的基础上新建节点node*/mxmlNewText(node, 0, "val1"); /*设置当前节点node的文本为val1*/node = mxmlNewElement(data, "node"); /*基于根节点data的基础上新建节点node*/mxmlNewText(node, 0, "val2"); /*设置当前节点node的文本为val2*/node = mxmlNewElement(data, "node"); /*基于根节点data的基础上新建节点node*/mxmlNewText(node, 0, "val3"); /*设置当前节点node的文件为val3*/group = mxmlNewElement(data, "group"); /*基于根节点data的基础上新建节点group*/node = mxmlNewElement(group, "group_node"); /*基于节点group的基础上新建节点group_node*/mxmlNewText(node, 0, "val4"); /*设置当前节点group_node的文本为val4*/node = mxmlNewElement(group, "group_node"); /*基于节点group的基础上新建节点group_node*/mxmlNewText(node, 0, "val5"); /*设置当前节点group_node的文本为val5*/node = mxmlNewElement(group, "group_node"); /*基于节点group的基础上新建节点group_node*/mxmlNewText(node, 0, "val6"); /*设置当前节点group_node的文本为val6*/node = mxmlNewElement(data, "node"); /*基于根节点data的基础上新建节点node*/mxmlNewText(node, 0, "val7"); /*设置当前节点node的文本为val7*/node = mxmlNewElement(data, "node"); /*基于根节点data的基础上新建节点node*/mxmlNewText(node, 0, "val8"); /*设置当前节点node的文本为val8*/FILE *fp; /*新建文件流指针 fp*/fp = fopen("demo.xml","wb"); /*新建或者打开demo.xml*/mxmlSaveFile(xml,fp,whitespace_cb); /*将数据保存到文件*/fclose(fp); /*关闭文件流指针*/mxmlDelete(xml); /*关闭xml根节点*/return 0;
}
编译后生成文件如下:
1.2、经典实例Demo_2
<?xml version="1.0" encoding="utf-8"?>
<data type="val"><node>val1</node><node>val2</node><node>val3</node><group><group_node>val4</group_node><group_node>val5</group_node><group_node>val6</group_node></group><node>val7</node><node>val8</node>
</data>
从配置文件中读取数据
#include "config.h"
#include "mxml.h"
#include "mxml-private.h"int main()
{FILE *fp; /*定义流指针*/fp = fopen("demo.xml","r"); /*打开文件demo.xml*/ mxml_node_t *tree,*data,*group,*node; /*定义节点指针*/tree = mxmlLoadFile(NULL,fp,MXML_NO_CALLBACK); /*获取当前xml的根节点*/data = mxmlWalkNext(tree,tree,MXML_DESCEND); /*从根节点data*/data = mxmlWalkNext(data,tree,MXML_NO_DESCEND); /*向下寻找子节点*/printf("获取属性:%s\n",mxmlElementGetAttr(data,"type")); /*输出当前节点的属性*/node = mxmlWalkNext(data,tree,MXML_DESCEND); /*data寻找下一级的节点*/node = mxmlWalkNext(node,tree,MXML_NO_DESCEND); /*node寻找同级的节点*/printf("获取文本:%s\n",mxmlGetText(node,NULL));node = mxmlWalkNext(node,tree,MXML_NO_DESCEND); /*node寻找同级的节点*/node = mxmlWalkNext(node,tree,MXML_NO_DESCEND); /*node寻找同级的节点*/printf("获取文本:%s\n",mxmlGetText(node,NULL));node = mxmlWalkNext(node,tree,MXML_NO_DESCEND); /*node寻找同级的节点*/node = mxmlWalkNext(node,tree,MXML_NO_DESCEND); /*node寻找同级的节点*/printf("获取文本:%s\n",mxmlGetText(node,NULL)); node = mxmlWalkNext(node,tree,MXML_NO_DESCEND); /*node寻找同级的节点*/node = mxmlWalkNext(node,tree,MXML_NO_DESCEND); /*node寻找同级的节点*/group = mxmlWalkNext(node,tree,MXML_DESCEND); /*node寻找下一级的节点*/group = mxmlWalkNext(group,tree,MXML_NO_DESCEND); /*group寻找同级的级节点*/printf("获取文本:%s\n",mxmlGetText(group,NULL)); group = mxmlWalkNext(group,tree,MXML_NO_DESCEND); /*group寻找同级的级节点*/group = mxmlWalkNext(group,tree,MXML_NO_DESCEND); /*group寻找同级的级节点*/printf("获取文本:%s\n",mxmlGetText(group,NULL)); group = mxmlWalkNext(group,tree,MXML_NO_DESCEND); /*group寻找同级的级节点*/group = mxmlWalkNext(group,tree,MXML_NO_DESCEND); /*group寻找同级的级节点*/printf("获取文本:%s\n",mxmlGetText(group,NULL));node = mxmlWalkNext(node,tree,MXML_NO_DESCEND); /*node寻找同级的节点*/node = mxmlWalkNext(node,tree,MXML_NO_DESCEND); /*node寻找同级的节点*/printf("获取文本:%s\n",mxmlGetText(node,NULL));node = mxmlWalkNext(node,tree,MXML_NO_DESCEND); /*node寻找同级的节点*/node = mxmlWalkNext(node,tree,MXML_NO_DESCEND); /*node寻找同级的节点*/printf("获取文本:%s\n",mxmlGetText(node,NULL)); return 0;
}
编译后如下:
代码解析:
1、mxmlLoadFile:载入一个文件到一个XML节点树。
mxml_node_t *mxmlLoadFile ( mxml_node_t *top, FILE *fp, mxml_load_cb_t cb
);
参数
top :顶级节点
fp:准备读取的文件
cb:回调函数或MXML_NO_CALLBACK
返回值:第一个节点或者NULL代表文件不能被读取。
2、mxmlWalkNext:遍历到XML树中的下一个逻辑节点。
mxml_node_t *mxmlWalkNext ( mxml_node_t *node, mxml_node_t *top, int descend
);
参数
node:当前节点
top:顶级节点
descend:在XML树中的向下搜索模式 - MXML_DESCEND, MXML_NO_DESCEND, 或者 MXML_DESCEND_FIRST。
返回值:下一个节点或者NULL
3、mxmlElementGetAttr:获取一个参数
const char *mxmlElementGetAttr ( mxml_node_t *node, const char *name
);
参数
node:XML元素节点
name:属性名称
返回值:属性值或者NULL
4、mxmlGetText:获取元素节点文本
const char *mxmlElementGetAttr ( mxml_node_t *node, NULL
);
参数
node:XML节点
返回值:文本
1.3、经典实例Demo_3
<?xml version="1.0" encoding="utf-8"?>
<Data><animal Dog = "第一只狗" ><name>白狗</name><nature>暴躁</nature></animal> <animal Dog = "第二只狗" ><name>黄狗</name><nature>温顺</nature></animal><animal Dog = "第三只狗" ><name>黑够</name> <nature>孤僻</nature></animal>
</Data>
循环获取数据
#include "stdio.h"
#include "mxml.h"
#include "config.h"
#include "mxml-private.h"
int main()
{FILE* fp = fopen("dog.xml","r");mxml_node_t* data = mxmlLoadFile(NULL,fp,MXML_NO_CALLBACK); /*获取当前节点信息*/mxml_node_t* animal = mxmlFindElement(data,data,"animal",NULL,NULL,MXML_DESCEND); /*寻找animal节点*/printf("%s的名字是",mxmlElementGetAttr(animal,"Dog"));mxml_node_t* name = mxmlFindElement(data,data,"name",NULL,NULL,MXML_DESCEND); /*寻找name节点*/printf("%s他的性格",mxmlGetText(name,NULL));mxml_node_t* nature = mxmlFindElement(data,data,"nature",NULL,NULL,MXML_DESCEND); /*寻找nature节点*/printf("%s\n",mxmlGetText(nature,NULL));while(1){animal = mxmlFindElement(animal,data,"animal",NULL,NULL,MXML_DESCEND);if(animal==NULL){break;}printf("%s的名字是",mxmlElementGetAttr(animal,"Dog"));name = mxmlFindElement(name,data,"name",NULL,NULL,MXML_DESCEND);printf("%s他的性格",mxmlGetText(name,NULL));nature = mxmlFindElement(nature,data,"nature",NULL,NULL,MXML_DESCEND);printf("%s\n",mxmlGetText(nature,NULL)); }mxmlDelete(data);fclose(fp); return 0;
}
编译运行如下:
二、总结
Mini-XML是一个小型的Xml解析库,在嵌入式应用程序开发,有着广泛的应用。