8.1 xml
minixml官网地址:http://www.msweet.org/projects.php/Mini-XML
其他解析xml开源库:tinyxml
pugixml
包含头文件:
mxml.h
- 编译的时候需要添加动态库:
libmxml.so
-lmxml
/usr/local/lib
8.2 xml文件格式
<!-- 新目录需要一个文件头 - 标准 -->
<?xml version="1.0" encoding="utf-8"?>
<!-- 必须有一个根节点(元素)--有且仅有一个 -->
<root>
<!-- xml标签对大小写敏感、标签大多成对出现,有开始、结束 -->
<child>
<!-- 这是一对标签 -->
</child>
<Child /> <!-- 这是但标签 -->
<!-- child 和 Child 是两个不同的标签 -->
<!-- 标签中可以添加属性 -->
<person>
<!-- report是name的属性,yes是report的值,属性值必须加引号 -->
<name report="yes">zhangsan</name>
</person>
</root>
示例:
<?xml version="1.0" encoding="utf-8"?>
<car>
<factory name="A">
<brand>
<name>A_car_1</name>
<color>red</color>
<price>10W</price>
</barnd>
<brand>
<name>A_car_2</name>
<color>blue</color>
<price>15W</price>
</barnd>
</factory>
<factory name="B">
<brand>
<name>B_car_1</name>
<color>white</color>
<price>20W</price>
</barnd>
<brand>
<name>B_car_2</name>
<color>black</color>
<price>25W</price>
</barnd>
</factory>
</car>
8.3 minixml安装
./configure --enable-threads=no && make
sudo make install
8.4 开源库minixml的使用
编译通过,但是运行是找不到动态库,但是动态库又在
/usr/local/lib
目录中
错误信息如下:
error while loading shared libraries: libmxml.so.1: cannot open shared object file: No such file or directory
查看动态库的链接路径:/etc/ld.so.conf
在路径包含的情况下执行:sudo /sbin/ldconfig -v
8.4.1 生成xml
根标签的对应的节点, 父亲节点是: 文件头节点
/*
* 函数功能:
* 创建一个新的xml文件,默认的文件的编码为utf8
* 参数:
* version:版本(1.0)
* 返回值:
* 成功:新创建的xml文件节点
*/
mxml_node_t *mxmlNewXML(const char *version);
/*
* 函数功能:
* 删除节点的内存
* 参数:
* node:节点指针
*/
void mxmlDelete(mxml_node_t *node);
/*
* 函数功能:
* 添加一个新的节点
* 参数:
* parent:父节点
* name:新节点标签名
* 返回值:
* 成功:新创建的节点
*/
mxml_node_t *mxmlNewElement(mxml_node_t *parent, const char *name);
/*
* 函数功能:
* 设置节点的属性名和属性值
* 参数:
* node:节点指针
* name:节点的属性名
* value:属性值
* 返回值:
* 成功:
*/
void mxmlElementSetAttr(mxml_node_t *node, const char *name, const char *value);
/*
* 函数功能:
* 创建节点的文本内容
* 参数:
* parent:节点地址
* whitespace:是否有空白 0
* string:文本内容
* 返回值:
* 成功:
*/
mxml_node_t *mxmlNewText (mxml_node_t *parent, int whitespace, const char *string);
/*
* 函数功能:
* 保存节点到xml文件
* 参数:
* node:根节点
* fp:文件指针
* cb:回调默认MXML_NO_CALLBACK
* 返回值:
* 成功:
*/
int mxmlSaveFile(mxml_node_t *node, FILE *fp, mxml_save_cb_t cb);
示例:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <mxml.h>
int main(int argc, const char *argv[])
{
// 创建一个文件头
mxml_node_t *root = mxmlNewXML("1.0");
// 根标签 china
mxml_node_t *country = mxmlNewElement(root, "country");
mxmlElementSetAttr(country, "name", "china");
// 子标签
mxml_node_t *city = mxmlNewElement(country, "city");
mxml_node_t *info = mxmlNewElement(city, "name");
// 标签赋值
mxmlNewText(info, 0, "beijing");
// 设置属性
mxmlElementSetAttr(info, "isbig", "Yes");
info = mxmlNewElement(city, "area");
mxmlNewText(info, 0, "16410平方公里");
info = mxmlNewElement(city, "population");
mxmlNewText(info, 0, "2170万");
info = mxmlNewElement(city, "gdp");
mxmlNewText(info, 0, "24541亿元");
// 保存
FILE *fp = fopen("china.xml", "w");
mxmlSaveFile(root, fp, MXML_NO_CALLBACK);
// 释放资源
fclose(fp);
mxmlDelete(root);
return 0;
}
8.4.2 解析xml
/*
* 函数功能:
* 从文件加载xml到内存
* 参数:
* top:一般为NULL
* fp:文件指针
* cb:回调、默认MXML_NO_CALLBACK
* 返回值:
* 成功:
*/
mxml_node_t *mxmlLoadFile(mxml_node_t *top, FILE *fp, mxml_type_t (*cb)(mxml_node_t *));
/*
* 函数功能:
* 获取节点的属性
* 参数:
* node:带属性的节点的地址
* name:属性名
* 返回值:
* 成功:
*/
const char *mxmlElementGetAttr(mxml_node_t *node, const char *name);
/*
* 函数功能:
* 获取指定节点的文本内容
* 参数:
* node:节点的地址
* whitespace:是否有空格
* cb:回调默认MXML_NO_CALLBACK
* 返回值:
* 成功:
*/
const char *mxmlGetText(mxml_node_t *node, int *whitespace);
/*
* 函数功能:
* 跳转到下一个节点
* 参数:
* node:当前节点
* top:根节点
* descend:
* MXML_NO_DESCEND:查看同层级
* MXML_DESCEND_FIRST:查看下一层级的第一个
* MXML_DESCEND:一直向下搜索
* 返回值:
* 成功:
*/
mxml_node_t *mxmlWalkNext(mxml_node_t *node, mxml_node_t *top, int descend);
/*
* 函数功能:
* 查找节点
* 参数:
* node:当前节点
* top:根节点
* name:查找的标签名
* attr:查找的标签的属性,没有属性传NULL
* value:查找的标签的属性值
* descend:
* MXML_NO_DESCEND:查看同层级
* MXML_DESCEND_FIRST:查看下一层级的第一个
* MXML_DESCEND:一直向下搜索
* 返回值:
* 成功:
*/
mxml_node_t *mxmlFindElement(mxml_node_t *node, mxml_node_t *top, const char *name, const char *attr, const char *value, int descend);
示例:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <mxml.h>
int main(int argc, const char *argv[])
{
if(argc < 2)
{
printf("error\n");
exit(-1);
}
// 价值xml文件
FILE *fp = fopen(argv[1], "r");
mxml_node_t *root = mxmlLoadFile(NULL, fp, MXML_NO_CALLBACK);
// 找到country
mxml_node_t *country = mxmlFindElement(root, root, "country", "name", NULL, MXML_DESCEND);
// 循环查找
while(country)
{
// 打印节点属性
printf("country name:%s\n", mxmlElementGetAttr(country, "name"));
// 向下一个节点移动
mxml_node_t *city = mxmlWalkNext(country, root, MXML_DESCEND);
while(city)
{
mxml_node_t *node = mxmlWalkNext(city, root, MXML_DESCEND);
printf("\t name:%s\n", mxmlGetText(node, 0));
node = mxmlWalkNext(node, root, MXML_DESCEND);
printf("\t area:%s\n", mxmlGetText(node, 0));
node = mxmlWalkNext(node, root, MXML_DESCEND);
printf("\t population:%s\n", mxmlGetText(node, 0));
node = mxmlWalkNext(node, root, MXML_DESCEND);
printf("\t gdp:%s\n", mxmlGetText(node, 0));
printf("-------------------------\n");
city = mxmlFindElement(city, root, "city", NULL, NULL, MXML_NO_DESCEND);
}
country = mxmlFindElement(country, root, "country", NULL, NULL, MXML_NO_DESCEND);
}
mxmlDelete(root);
fclose(fp);
return 0;
}
8.5 Json
8.5.1 json的格式
8.5.1.1 json数组
char array[23] = "slkjflajslfd"; // C 语言中数组
// 中括号[整形, 字符串, 布尔类型, json数组, json对象]
[123, 123.2, true, false, [12, 34, 56, "hello, world"]]
8.5.1.2 json对象
{}中是一些键值对
{
"name":"zhang3",
"name2":"li4"
}
key值: 必须是 字符串, 不重复
value值: json对象, json数组, 布尔, 整形, 字符串
8.5.1.3 json数组+对象
{
"name":"zhang3",
"name2":"li4",
"张三":{
"别名":"老王",
"性别":"男",
"年龄":34,
"孩子":["小红", "小绿", "小黑"]
}
}
一个文件中只能有一个对象或数组
示例:
[
{
"name":"zhangsan".
"age":18,
"height":178.5
},
{
"name":"lisi".
"age":19,
"height":174.5
}
]
8.6 C语言中json开源解析库 - cjson
8.6.1 cjson的使用
压缩包解压缩,直接使用里边的cJSON.c和cJSON.h即可
链接时还需要加上-lm 表示链接math库
8.6.2 生成json文件
/*
* 函数功能:
* 创建一个json对象
* 返回值:
* 成功:
* 失败:
*/
cJSON *cJSON_CreateObject(void);
/*
* 函数功能:
* 往json对象中添加数据成员
* 参数:
* object:json对象
* string:key值
* iten:value值(int、string、array、obj)
* 返回值:
* 成功:
* 失败:
*/
void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
/*
* 函数功能:
* 创建一个数
* 参数:
* num:数
* 返回值:
* 成功:
* 失败:
*/
cJSON *cJSON_CreateNumber(double num);
/*
* 函数功能:
* 创建一个字符串
* 参数:
*
* 返回值:
* 成功:
* 失败:
*/
cJSON *cJSON_CreateString(const char *string);
/*
* 函数功能:
* 创建一个json数组,空数组
* 参数:
*
* 返回值:
* 成功:
* 失败:
*/
cJSON *cJSON_CreateArray(void);
/*
* 函数功能:
* 创建默认有count个整形值的json数组
* 参数:
*
* 返回值:
* 成功:
* 失败:
*/
cJSON *cJSON_CreateIntArray(const int *numbers,int count);
/*
* 函数功能:
* 往json数组中添加数据成员
* 参数:
*
* 返回值:
* 成功:
* 失败:
*/
void cJSON_AddItemToArray(cJSON *array, cJSON *item);
/*
* 函数功能:
* 释放jSON结构指针
* 参数:
*
* 返回值:
* 成功:
* 失败:
*/
void cJSON_Delete(cJSON *c)
/*
* 函数功能:
* 将JSON结构转化为字符串
* 参数:
*
* 返回值:
* 成功:
* 失败:
*/
char *cJSON_Print(cJSON *item);
示例:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include "cJSON.h"
int main(int argc, const char *argv[])
{
// 创建json对象
cJSON *array = cJSON_CreateArray();
cJSON *obj = cJSON_CreateObject();
// obj中添加kek:value
cJSON_AddItemToObject(obj, "name", cJSON_CreateString("zhangsan"));
cJSON_AddItemToObject(obj, "age", cJSON_CreateNumber(18));
cJSON_AddItemToObject(obj, "height", cJSON_CreateNumber(178.5));
// obj中添加kek:value
cJSON_AddItemToArray(array,obj);
// 数据格式化
char *data = cJSON_Print(array);
// 写入文件
FILE *fp = fopen("person.json", "w");
fwrite(data, sizeof(char), strlen(data)+1, fp);
fclose(fp);
return 0;
}
8.6.3 解析json文件
/*
* 函数功能:
* 将字符串解析为JSON结构
* 参数:
*
* 返回值:
* 成功:
* 失败:
*/
cJSON *cJSON_Parse(const char *value);
/*
* 函数功能:
* 根据键值查找json节点
* 参数:
* object:当前json对象
* string:key值
* 返回值:
* 成功:
* 失败:
*/
cJSON *cJSON_GetObjectItem(cJSON *object, const char *string);
/*
* 函数功能:
* 获取json数组中元素的个数
* 参数:
*
* 返回值:
* 成功:
* 失败:
*/
int cJSON_GetArraySize(cJSON *array);
/*
* 函数功能:
* 根据数组下标找到对应的数组元素
* 参数:
*
* 返回值:
* 成功:
* 失败:
*/
cJSON *cJSON_GetArrayItem(cJSON *array, int index);
/*
* 函数功能:
* 判断是否有可以值对应的键值对
* 参数:
*
* 返回值:
* 成功:
* 失败:
*/
int cJSON_HasObjectItem(cJSON *object, const char *string)
cJSON结构体:
#define cJSON_Invalid (0)
#define cJSON_False (1 << 0)
#define cJSON_True (1 << 1)
#define cJSON_NULL (1 << 2)
#define cJSON_Number (1 << 3)
#define cJSON_String (1 << 4)
#define cJSON_Array (1 << 5)
#define cJSON_Object (1 << 6)
#define cJSON_Raw (1 << 7)
/* The cJSON structure: */
typedef struct cJSON
{
struct cJSON *next;
struct cJSON *prev;
struct cJSON *child;
int type;
char *valuestring;
int valueint;
double valuedouble;
char *string;
}cJSON;
示例:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include "cJSON.h"
int main(int argc, const char *argv[])
{
// 读取文件信息
FILE *fp = fopen(argv[1], "r");
char data[1024] = { 0 };
fread(data, sizeof(char), sizeof(data), fp);
// 将字符串解析为Json结构
cJSON *array = cJSON_Parse(data);
// 获取元素个数
int n = cJSON_GetArraySize(array);
// 遍历
for(int i = 0;i < n;++i)
{
cJSON *obj = cJSON_GetArrayItem(array, i);
cJSON *name = cJSON_GetObjectItem(obj, "name");
cJSON *age = cJSON_GetObjectItem(obj, "age");
cJSON *height = cJSON_GetObjectItem(obj, "height");
printf("name:%s\nage:%d\nheight:%.2lf\n", name->valuestring, age->valueint, height->valuedouble);
}
return 0;
}