Linux C编程第二十章XML-JSON

网友投稿 1092 2022-05-29

一、XML

1. minixml官网地址

http://www.msweet.org/projects.php/Mini-XML

其他解析xml开源库:tinyxml pugixml

1)包含头文件: mxml.h

2)编译的时候需要添加动态库: libmxml.so

-lmxml

/usr/local/lib

2. minixml安装:

./configure --enable-threads=no && make

sudo make install

3. 新目录需要一个文件头 - 标准

version不可以省略

encoding可以省略

4. 使用注意事项

必须有一个根元素(节点) -- (只有一个)

xml标签对大小写敏感

标签大多成对使用, 有开始, 有结束

5. 标签中可以添加属性

属性值必须加引号

6. 标签注释

7. 开源库minixml的使用

(1)跟标签的对应的节点,父亲节点是:文件头节点

(2)生成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 );

(3)解析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, // 查找的标签名 const char *attr, // 查找的标签的属性,没有属性传NULL const char *value, // 查找的标签的属性值,没有属性传NULL int descend // 同上 );

8. 示例

(1)生成下面的xml

create_xml.xml

1 2 3 4 哈利波特 5 JK.Rowling 6 2005 7 29.99 8 9

create.c

parsexml.c

1 #include 2 #include "mxml.h" 3 4 int main(int argc, const char* argv[]) 5 { 6 // 加载xml文件 7 FILE* fp = fopen("book.xml", "r"); 8 mxml_node_t* root = mxmlLoadFile(NULL, fp, MXML_NO_CALLBACK); 9 10 // 查找book节点 11 mxml_node_t* book = mxmlFindElement(root, root, "book", "category", NULL, MXML_DESCEND); 12 printf("book attr: %s\n", mxmlElementGetAttr(book, "category")); 13 14 mxml_node_t* node = mxmlWalkNext(book, root, MXML_DESCEND_FIRST); 15 printf(" title: %s\n", mxmlGetText(node, 0)); 16 17 node = mxmlWalkNext(node, root, MXML_NO_DESCEND); 18 printf(" author: %s\n", mxmlGetText(node, 0)); 19 20 node = mxmlWalkNext(node, root, MXML_NO_DESCEND); 21 printf(" year: %s\n", mxmlGetText(node, 0)); 22 23 node = mxmlWalkNext(node, root, MXML_NO_DESCEND); 24 printf(" price: %s\n", mxmlGetText(node, 0)); 25 26 fclose(fp); 27 28 mxmlDelete(root); 29 30 return 0; 31 }

(2)生成下面的xml

create_xml.xml

1 2 3 4 北京 5 1.641万平方千米 6 2200万 7 8 9 石家庄 10 15848平方千米 11 107万 12 13

create.c

1 #include 2 #include 3 4 int main(int argc, const char* argv[]) 5 { 6 // 创建xml文件头节点 7 mxml_node_t *xml = mxmlNewXML("1.0"); 8 9 // 创建xml根节点 - china 10 mxml_node_t* china = mxmlNewElement(xml, "China"); 11 12 13 // 创建城市节点 14 mxml_node_t* city = mxmlNewElement(china, "City"); 15 // 添加子节点 16 // name 17 mxml_node_t* name = mxmlNewElement(city, "Name"); 18 // 设置标签值 19 mxmlNewText(name, 0, "北京"); 20 mxmlElementSetAttr(name, "isbig", "true"); 21 // 面积 22 mxml_node_t* area = mxmlNewElement(city, "Area"); 23 mxmlNewText(area, 0, "1.641万平方千米"); 24 // 人口 25 mxml_node_t* popu = mxmlNewElement(city, "Population"); 26 mxmlNewText(popu, 0, "2200万"); 27 28 // 第二个城市节点 29 city = mxmlNewElement(china, "City"); 30 // name 31 name = mxmlNewElement(city, "Name"); 32 mxmlNewText(name, 0, "石家庄"); 33 mxmlElementSetAttr(name, "isbig", "false"); 34 area = mxmlNewElement(city, "Area"); 35 mxmlNewText(area, 0, "15848平方千米"); 36 popu = mxmlNewElement(city, "Population"); 37 mxmlNewText(popu, 0, "107万"); 38 39 // 将xml内容保存到磁盘 40 FILE* fp = fopen("china.xml", "w"); 41 mxmlSaveFile(xml, fp, MXML_NO_CALLBACK); 42 fclose(fp); 43 mxmlDelete(xml); 44 45 return 0; 46 }

parse_xml.c

1 #include 2 #include 3 4 int main(int argc, const char* argv[]) 5 { 6 // 从磁盘加载xml文件 7 FILE* fp = fopen("china.xml", "r"); 8 if(fp == NULL) 9 { 10 printf("fopen error\n"); 11 return 0; 12 } 13 // root 节点指向xml文件头 14 mxml_node_t* root = mxmlLoadFile(NULL, fp, MXML_NO_CALLBACK); 15 16 // 遍历 - 取出各个节点的值 17 // 找到第一个城市节点 18 mxml_node_t* city = mxmlFindElement(root, root, "City", NULL, NULL, MXML_DESCEND); 19 if(city == NULL) 20 { 21 printf("xml node not found\n"); 22 return 0; 23 } 24 while( city ) 25 { 26 printf("==================\n"); 27 // 向下走一个节点 28 mxml_node_t* node = mxmlWalkNext(city, root, MXML_DESCEND_FIRST); 29 printf("city: \n"); 30 printf(" name = %s\n", mxmlGetText(node, NULL)); 31 // 32 node = mxmlWalkNext(node, root, MXML_NO_DESCEND); 33 printf(" area = %s\n", mxmlGetText(node, NULL)); 34 // 35 node = mxmlWalkNext(node, root, MXML_NO_DESCEND); 36 printf(" population = %s\n", mxmlGetText(node, NULL)); 37 // 搜索下一个城市节点 38 city = mxmlFindElement(city, root, "City", NULL, NULL, MXML_DESCEND); 39 } 40 41 fclose(fp); 42 mxmlDelete(root); 43 44 return 0; 45 }

(3)xml 解析注意问题

注意:使用 minixml 开源库生成的 xml 会在一行,如果手动将调整 xml,则解析会有问题。下面的示例相同的xml,只是将在一行的xml进行调整,注意运行查看解析结果。

car1.xml

1 2 3 4 一汽大众 5 6 高尔夫 7 红色 8 15万 9 10 11 速腾 12 银白 13 18万 14 15 16 迈腾 17 黑灰 18 28万 19 20 21 22 23 帕萨特 24 黑色 25 25万 26 27 28 POLO 29 灰色 30 8万 31 32 33

car2.xml

1 高尔夫红色15万速腾银白18万迈腾黑灰28万帕萨特黑色25万POLO灰色8万

parsecar.c

1 #include 2 #include "mxml.h" 3 4 int main(int argc, const char* argv[]) 5 { 6 if(argc < 2) 7 { 8 printf("./a.out filename\n"); 9 return 0; 10 } 11 // 加载xml文件 12 FILE* fp = fopen(argv[1], "r"); 13 mxml_node_t* root = mxmlLoadFile(NULL, fp, MXML_NO_CALLBACK); 14 15 // 找到第一个factory节点 16 mxml_node_t* factory = mxmlFindElement(root, root, "factory", "name", NULL, MXML_DESCEND); 17 // 循环查找 18 while( factory ) 19 { 20 // 打印几点的属性值 21 printf("factory attr: %s\n", mxmlElementGetAttr(factory, "name")); 22 23 // 向下移动一个节点 24 mxml_node_t* brand = mxmlWalkNext(factory, root, MXML_DESCEND); 25 while( brand ) 26 { 27 // name 28 mxml_node_t* node = mxmlWalkNext(brand, root, MXML_DESCEND_FIRST); 29 printf(" name: %s\n", mxmlGetText(node, 0)); 30 // color 31 node = mxmlWalkNext(node, root, MXML_NO_DESCEND); 32 printf(" color: %s\n", mxmlGetText(node, 0)); 33 // price 34 node = mxmlWalkNext(node, root, MXML_NO_DESCEND); 35 printf(" price: %s\n", mxmlGetText(node, 0)); 36 printf(" =========================================\n"); 37 38 // 找到下一个品牌节点 39 brand = mxmlFindElement(brand, root, "brand", NULL, NULL, MXML_NO_DESCEND); 40 } 41 // 打印该厂家对应的车辆品牌和属性信息 42 // 查找下一个节点 43 factory = mxmlFindElement(factory, root, "factory", "name", NULL, MXML_NO_DESCEND); 44 } 45 mxmlDelete(root); 46 fclose(fp); 47 48 return 0; 49 }

上面代码编译:gcc c文件 -lmxml -lpthread

二、JSON

1. cjson的使用

压缩包解压缩,直接使用里边的cJSON.c和cJSON.h即可

链接时还需要加上-lm 表示链接math库

2. json数组

char array[23] = "slkjflajslfd";

中括号[整形, 字符串, 布尔类型, json数组, json对象],比如[123, 123.2, true, false, [12, 34, 56, "hello, world"]]

3. json对象

{}中是一些键值对

{ "name":"zhang3", "name2":"li4" } key值: 必须是 字符串, 不重复 value值: json对象, json数组, 布尔, 整形, 字符串

4. json数组+json对象

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

5. C语言json开源解析库 - cjson

(1)生成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);

【Linux C编程】第二十章XML-JSON

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();

(2)解析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);

示例:

JSON Linux XML

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:操作系统——进程间通信
下一篇:看完令你大彻大悟的22道经典Redis面试题,附带答案(下)
相关文章