Mini-Xml 经典实例Demo

news/2024/10/30 9:25:19/

欢迎小伙伴的点评✨✨,相互学习、博主将自己研发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解析库,在嵌入式应用程序开发,有着广泛的应用。


http://www.ppmy.cn/news/33094.html

相关文章

基于STM32 + FPGA 的软体机器人的 CAN总线运动控制器的设计

针对在软体机器人控制时&#xff0c;多电机协同控制过程中难度大、通用性差、协同性差等缺点&#xff0c;设计了基于 A&#xff32;M和 FPGA的软体机器人的控制器局域网络 ( controller area network&#xff0c;CAN) 总线运动控制器&#xff0c;采用 A&#xff32;MCortex-M4 …

【c++】:STL中vector的模拟使用及模拟实现

文章目录 前言一.使用库中vector常用接口二.vector的模拟实现总结前言 上一篇我们讲解了STL中的string的使用和模拟实现&#xff0c;这次我们就来讲解STL中的vector&#xff0c;vector相对于string来说模拟实现会难一些&#xff0c;难点在于迭代器失效问题和深浅拷贝问题。 首…

22讲MySQL有哪些“饮鸩止渴”提高性能的方法

短连接风暴 是指数据库有很多链接之后只执行了几个语句就断开的客户端&#xff0c;然后我们知道数据库客户端和数据库每次连接不仅需要tcp的三次握手&#xff0c;而且还有mysql的鉴权操作都要占用很多服务器的资源。话虽如此但是如果连接的不多的话其实这点资源无所谓的。 但是…

【MySQL】表的数据处理

哈喽&#xff0c;大家好&#xff01;我是保护小周ღ&#xff0c;本期为大家带来的是 MySQL 数据表中数据的基本处理的操作&#xff0c;数据表的增删改查&#xff0c;更多相关知识敬请期待&#xff1a;保护小周ღ *★,*:.☆(&#xffe3;▽&#xffe3;)/$:*.★*一、 添加数据&a…

【C++进阶】对象的使用

static成员 对于特定类型的全体对象而言&#xff0c;有时候可能需要访问一个全局的变量。比如说统计某种类型对象已创建的数量。如果我们用全局变量会破坏数据的封装&#xff0c;一般的用户代码都可以修改这个全局变量&#xff0c;这时我们可以用类的静态成员来解决这个问题。…

Linux虚拟机磁盘扩容、Docker容器磁盘满的问题、Docker安装nginx

文章目录虚拟机扩容1、外部配置2、具体扩容步骤3、扩容后效果Docker容器磁盘满的情况意外情况使用docker安装nginx前言 在创建虚拟机的时候&#xff0c;分配的磁盘空间只有40个G。使用了一段时间后&#xff0c;系统提示磁盘空间满了。在使用Docker安装镜像的时候&#xff0c;由…

C语言实现单链表(超多配图,这下不得不学会单链表了)

目录 一&#xff1a;什么是链表&#xff1f; 二&#xff1a;创建源文件和头文件 (1)头文件 (2)源文件 三&#xff1a;实参和形参 四&#xff1a;一步步实现单向链表 &#xff08;1&#xff09;建立一个头指针并置空 &#xff08;2&#xff09;打印链表&#xff0c;便于…

技术掉:PDF显示,使用pdf.js

PDF 显示 场景&#xff1a; 其实直接显示 pdf 可以用 iframe 标签&#xff0c;但产品觉得浏览器自带的 pdf 预览太丑了&#xff0c;而且无法去除那些操作栏。 解决方案&#xff1a;使用 pdf.js 进行显示 第一步&#xff1a;引入 pdf.js 去官网下载稳定版的 pdf.js 文件 然后…