欢迎小伙伴的点评✨✨,相互学习、博主将自己研发xml微型服务器的经验与之分享
本章将会给大家带来mini-xml的基本实例解析
mxml 环境配置
#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",则在节点前加入回车*/
{
return ("\n");
}else if(where == MXML_WS_BEFORE_CLOSE) /*如果name == "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;
}
<data type="val">
<node>val1node>
<node>val2node>
<node>val3node>
<group>
<group_node>val4group_node>
<group_node>val5group_node>
<group_node>val6group_node>
group>
<node>val7node>
<node>val8node>
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节点
返回值:文本
<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解析库,在嵌入式应用程序开发,有着广泛的应用。