Linux网络编程-8.xml,Json

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;
}
  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT灰猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值