linux高并发网络编程开发(xml json)16_xml和Json相关api及文件解析制作

pdf详细版

01 学习目标

xml

  • xml基础语法和规范
  • C程序中如何使用xml开源库
  • 借助开源库,在C程序中生成xml文件
  • 已知一个xml文件,如何借助开源库解析xml文件数据

Json

  • json的基础语法和规范
  • C程序中如何使用json开源库 - cjson
  • 使用cjson生成json文件
  • 已知一个json文件,使用cjson库解析文件数据

02 xml文件格式

<!-- 注释 -->
<!-- 文件头 -->
<?xml version="1.0" encoding="UTF-8"?>
<!-- 树状结构的标签 -->
<!-- 根标签 -- 自个起名   只有一个 -->
<!-- 标签的值区分大小写 -->


<!-- 标签一般成对出现 -->
<Zhangsan>
	<!-- 不成对 -->
	<lisi/>
	<!-- 子标签 -->
	<child>
		<!-- 没有子标签, 标签必须有值 -->
		<!-- 标签可以设置属性 report: 属性, 属性值需要使用""包含-->
		<name report="yes">zhang1</name>
		<age yefen="1">12</age>
		<sex>男</sex>
	</child>
	<!-- 子标签 -->
	<child>
		<name>zhang2</name>
		<age>4</age>
		<sex>女</sex>
	</child>
</Zhangsan>

03 xml示例文件

<?xml version="1.0" encoding="utf-8"?>
<car>
	<factory>
		<name>一汽大众</name>
		<brand>
			<name>高尔夫</name>
			<color>红色</color>
			<price>15万</price>
		</brand>
		<brand>
			<name>速腾</name>
			<color>银白</color>
			<price>18万</price>
		</brand>
		<brand>
			<name>迈腾</name>
			<color>黑灰</color>
			<price>28万</price>
		</brand>
	</factory>
	<factory>
		<brand>
			<name>帕萨特</name>
			<color>黑色</color>
			<price>25万</price>
		</brand>
		<brand>
			<name>POLO</name>
			<color>灰色</color>
			<price>8万</price>
		</brand>
	</factory>
</car>

04 xml文件的设计

在这里插入图片描述

<?xml version="1.0" encoding="utf-8"?>
<China>
	<City>
		<Name isbig="true">北京</Name>
		<Area>1.641万平方千米</Area>
		<Population>2200万</Population>
	</City>
	<City>
		<Name isbig="false">石家庄</Name>
		<Area>15848平方千米</Area>
		<Population>107万</Population>
	</City>
</China>

05 mxml安装和配置

minixml官网地址
http://www.msweet.org/projects.php/Mini-XML
其他解析xml开源库:tinyxml pugixml
○ 包含头文件: mxml.h
○ 编译的时候需要添加动态库: libmxml.so
▪ -lmxml
▪ /usr/local/lib

  1. minixml安装:
    ○ ./configure --enable-threads=no && make
    ○ sudo make install

  2. 新目录需要一个文件头 - 标准
    ○ <?xml version="1.0" encoding="utf-8"?>
    ○ version不可以省略
    ○ encoding可以省略

  3. 使用注意事项
    ○ 必须有一个根元素(节点) – (只有一个)
    ○ xml标签对大小写敏感
    ○ 标签大多成对使用, 有开始, 有结束

<date></date>
<time></time>
  1. 标签中可以添加属性

    ○ 属性值必须加引号.

  2. 标签注释
    <!-- 这是注释 -->

06 mxml生成文件函数介绍

开源库minixml的使用
○ 跟标签的对应的节点, 父亲节点是: 文件头节点
○ 生成xml文件
1.创建一个新的xml文件

mxml_node_t *mxmlNewXML(const char *version);

□ 返回新创建的xml文件节点.
□ 默认的文件的编码为utf8

2.删除节点的内存

void mxmlDelete(mxml_node_t *node);

3.添加一个新的节点

mxml_node_t *mxmlNewElement(
mxml_node_t *parent, // 父节点
const char *name // 新节点标签名
);

4.设置节点的属性名和属性值

void mxmlElementSetAttr(
mxml_node_t *node, // 被设置属性的节点
const char *name, // 节点的属性名
const char *value // 属性值
);

5.创建节点的文本内容

mxml_node_t *mxmlNewText (
mxml_node_t *parent, // 节点地址
int whitespace, // 是否有空白 0
const char *string // 文本内容
);

6.保存节点到xml文件

int mxmlSaveFile(
mxml_node_t *node, // 根节点
FILE *fp, // 文件指针
mxml_save_cb_t cb // 默认MXML_NO_CALLBACK
);

07 使用mxml api生成xml文件

xml_create.c:

#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* china = mxmlNewElement(root, "china");
    // 子标签 -- city
    mxml_node_t* city = mxmlNewElement(china, "city");
    mxml_node_t* info = mxmlNewElement(city, "name");
    // 标签赋值
    mxmlNewText(info, 0, "北京");
    // 设置属性
    mxmlElementSetAttr(info, "isbig", "Yes");
    // 面积
    info = mxmlNewElement(city, "area");
    mxmlNewText(info, 0, "16410 平方公里");
    // 人口
    info = mxmlNewElement(city, "population");
    mxmlNewText(info, 0, "2171万人");
    // gdp
    info = mxmlNewElement(city, "gdp");
    mxmlNewText(info, 0, "24541亿元");

    // 东京
    city = mxmlNewElement(china, "city");
    info = mxmlNewElement(city, "name");
    // 标签赋值
    mxmlNewText(info, 0, "东京");
    // 设置属性
    mxmlElementSetAttr(info, "isbig", "No");
    // 面积
    info = mxmlNewElement(city, "area");
    mxmlNewText(info, 0, "2188 平方公里");
    // 人口
    info = mxmlNewElement(city, "population");
    mxmlNewText(info, 0, "3670万人");
    // gdp
    info = mxmlNewElement(city, "gdp");
    mxmlNewText(info, 0, "31700亿元");

    // 数据保存到磁盘文件
    FILE* fp = fopen("china.xml", "w");
    mxmlSaveFile(root, fp, MXML_NO_CALLBACK);
    
    fclose(fp);
    mxmlDelete(root);

    return 0;
}

08 mxml获取文件数据api

○ 解析xml文件
1.从文件加载xml到内存

mxml_node_t *mxmlLoadFile(
mxml_node_t *top, // 一般为NULL
FILE *fp, // 文件指针
mxml_type_t (*cb)(mxml_node_t *) // 默认MXML_NO_CALLBACK
);

2.获取节点的属性

const char *mxmlElementGetAttr(
mxml_node_t *node, // 带属性的节点的地址
const char *name // 属性名
);

3.获取指定节点的文本内容

const char *mxmlGetText(
mxml_node_t *node, // 节点的地址
int *whitespace // 是否有空格
);

4.跳转到下一个节点

mxml_node_t *mxmlWalkNext(
mxml_node_t *node, // 当前节点
mxml_node_t *top, // 根节点
int descend
);

descend:搜索的规则
 MXML_NO_DESCEND:查看同层级
 MXML_DESCEND_FIRST:查看下一层级的第一个
 MXML_DESCEND:一直向下搜索

5.查找节点

mxml_node_t *mxmlFindElement(
mxml_node_t *node, // 当前节点
mxml_node_t *top, // 根节点
const char *name, // 查找的标签名
没有属性传NULL
const char *attr, // 查找的标签的属性
const char *value, // 查找的标签的属性值
int descend // 同上
);

09 mxml格式文件解析

parse_xml.c:

#include <stdio.h>
#include <mxml.h>

int main(int argc, const char* argv[])
{
    // 从磁盘加载xml文件
    FILE* fp = fopen("china.xml", "r");
    if(fp == NULL)
    {
        printf("fopen error\n");
        return 0;
    }
    // root 节点指向xml文件头
    mxml_node_t* root = mxmlLoadFile(NULL, fp, MXML_NO_CALLBACK);

    // 遍历 - 取出各个节点的值
    // 找到第一个城市节点
    mxml_node_t* city = mxmlFindElement(root, root, "City", NULL, NULL, MXML_DESCEND);
    if(city == NULL)
    {
        printf("xml node not found\n");
        return 0;
    }
    while( city  )
    {
        printf("==================\n");
        // 向下走一个节点
        mxml_node_t* node = mxmlWalkNext(city, root, MXML_DESCEND_FIRST);
        printf("city:   \n");
        printf("    name = %s\n", mxmlGetText(node, NULL));
        // 
        node = mxmlWalkNext(node, root, MXML_NO_DESCEND);
        printf("    area = %s\n", mxmlGetText(node, NULL));
        //
        node = mxmlWalkNext(node, root, MXML_NO_DESCEND);
        printf("    population = %s\n", mxmlGetText(node, NULL));
        // 搜索下一个城市节点
        city = mxmlFindElement(city, root, "City", NULL, NULL, MXML_DESCEND);
    }

    fclose(fp);
    mxmlDelete(root);

    return 0;
}

10 json文件格式

  1. cjson的使用
  • 压缩包解压缩,直接使用里边的cJSON.c和cJSON.h即可
  • 链接时还需要加上-lm 表示链接math库
  1. json的格式
  • json数组
    ○ char array[23] = “slkjflajslfd”; - c
    ○ 中括号[整形, 字符串, 布尔类型, json数组, json对象]
    ○ [123, 123.2, true, false, [12, 34, 56, “hello, world”]]

  • json对象
    {}中是一些键值对
    ▪ {
    “name”:“zhang3”,
    “name2”:“li4”
    }
    ▪ key值: 必须是 字符串, 不重复
    ▪ value值: json对象, json数组, 布尔, 整形, 字符串

  • json数组+json对象

{
	"name":"zhang3", 
	"name2":"li4",
	"张三":{
		"别名":"老王",
		"性别":"男",
		"年龄":34,
		"孩子":["小红", "小绿", "小黑"]
	}
}

11 json格式示例文件

{
	"奔驰":	{
		"factory":	"一汽大众",
		"last":	31,
		"price":	83,
		"sell":	49,
		"sum":	80,
		"other":	[124, "hello, world", false]
	}
}

12 cjon介绍

C语言json开源解析库 - cjson
○ 生成json文件
1.创建一个json对象

cJSON *cJSON_CreateObject(void);

2.往json对象中添加数据成员

void cJSON_AddItemToObject(
cJSON *object, // json对象
const char *string, // key值
cJSON *item // value值(int,string,array,obj)
);

3.创建一个整型值

cJSON *cJSON_CreateNumber(double num);

4.创建一个字符串

cJSON *cJSON_CreateString(const char *string);

5.创建一个json数组

cJSON *cJSON_CreateArray(void); -- 空数组

6.创建默认有count个整形值的json数组

cJSON *cJSON_CreateIntArray(const int *numbers,int count);

▪ int arry[] = {8,3,4,5,6};
▪ cJSON_CreateIntArray(arry, 5);

7.往json数组中添加数据成员

void cJSON_AddItemToArray(cJSON *array, cJSON *item);

8.释放jSON结构指针

void cJSON_Delete(cJSON *c)

9.将JSON结构转化为字符串

char *cJSON_Print(cJSON *item);

▪ 返回值需要使用free释放
▪ FILE* fp = fopen();
▪ fwrite();
▪ fclose();

13 cjson api创建json文件

将cjson库的cJSON.h和cJSON.c文件复制到目录中
Json_create.c:

#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[])
{
    // 创建对象
    cJSON* obj = cJSON_CreateObject();

    // 创建子对象
    cJSON* subObj = cJSON_CreateObject();
    // 添加key-value
    cJSON_AddItemToObject(subObj, "factory", cJSON_CreateString("一汽大众"));
    cJSON_AddItemToObject(subObj, "last", cJSON_CreateNumber(31));
    cJSON_AddItemToObject(subObj, "price", cJSON_CreateNumber(83));
    cJSON_AddItemToObject(subObj, "sell", cJSON_CreateNumber(49));
    cJSON_AddItemToObject(subObj, "sum", cJSON_CreateNumber(80));

    // 创建json数组
    cJSON* array = cJSON_CreateArray();
    // array添加元素
    cJSON_AddItemToArray(array, cJSON_CreateNumber(123));
    cJSON_AddItemToArray(array, cJSON_CreateBool(1));
    cJSON_AddItemToArray(array, cJSON_CreateString("hello, world"));

    // 数组中的对象
    cJSON* subsub = cJSON_CreateObject();
    cJSON_AddItemToObject(subsub, "梅赛德斯奔驰", 
                          cJSON_CreateString("心所向, 持以恒"));
    cJSON_AddItemToArray(array, subsub);

    cJSON_AddItemToObject(subObj, "other", array);

    // obj中添加key - value
    cJSON_AddItemToObject(obj, "奔驰", subObj);

    // 数据格式化
    char* data = cJSON_Print(obj);
    FILE* fp = fopen("car.json", "w");
    fwrite(data, sizeof(char), strlen(data)+1, fp);
    fclose(fp);

    return 0;
}

14 cjson解析api

○ 解析json文件
1.将字符串解析为JSON结构

cJSON *cJSON_Parse(const char *value);

▪ 返回值需要使用cJSON_Delete释放

2.根据键值查找json节点

cJSON *cJSON_GetObjectItem(
cJSON *object, // 当前json对象
const char *string // key值
);

3.获取json数组中元素的个数

int cJSON_GetArraySize(cJSON *array);

4.根据数组下标找到对应的数组元素

cJSON *cJSON_GetArrayItem(cJSON *array, int index);

5.判断是否有可以值对应的键值对

int cJSON_HasObjectItem(cJSON *object, const char *string)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值