# fastxml
**Repository Path**: microcolin/fastxml
## Basic Information
- **Project Name**: fastxml
- **Description**: 纯C编写的XML解析引擎
- **Primary Language**: C
- **License**: BSD-3-Clause-Clear
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 27
- **Created**: 2024-04-19
- **Last Updated**: 2024-04-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# fastxml 纯C语言编写的XML解析库 #
## 什么是fastxml? ##
**fastxml是一款支持XML解析的多根节点的解析引擎,支持特性如下:**
- 支持多根 **XML**,一个 **XML** 文档支持多个 ROOT 标记,如下包含`information` 和 `list`:
```xml
Josin
26
Changsha
Linux
v5.0.1
Git
```
- 支持**单一元素直接闭合**语法
```xml
Josin
26
Changsha
```
- 支持XML文档声明,声明必须位于第一行,以及众多属性,标准的XML声明如下:
```xml
```
- **支持标记的属性特性**,如下面的 `information` 标记包含的 `id` 和 `pid` 属性:
```xml
Josin
26
Changsha
```
- 支持**注释**,**注意:注释不可以嵌套**
```xml
2
Changsha
```
- 支持 **CDATA标记** 防止浏览器转义
```xml
Hunan
```
- 暂不支持特性:**DTD规则以及校验**
## 编译 & 运行 ##
**fastxml** 使用纯C99语法编写,可以使用在支持标准C99的操作系统上,**fastxml**使用 cmake编译管理系统,推荐版本 3.13以及以上
```c
git clone https://gitee.com/josinli/fastxml.git
cd fastxml
mkdir build
cd build
cmake .. && make
./fastxml
```
## 性能测试 ##
性能测试基准平台:**MacBook Pro** ,**Linux** 平台性能更高, 解析大约22KB 的 XML 文档 1100 次耗时 1 秒
## APIs 列表
- 从字符串解析 **XML**,返回 **NULL** 表示XML文件格式错误
```c
CXML *new_cxml_from_string2(char *str, unsigned long long);
```
- 从CXML中编码为字符串,返回的字符串需要通过 **free** 函数释放
```c
char *new_string_from_cxml(CXML *c);
```
- 获取解码 XML 的错误信息
```c
char *new_cxml_get_error();
```
- 生成CXML对象
```c
CXML *cxml_new_cxml(char *tag, char *version, char *encoding);
```
- 给CXML对象添加根节点
```c
int cxml_add_root_node(CXML *xml, CXML_NODE *node);
```
- 生成CXML节点信息
```c
CXML_NODE *cxml_make_node(char *name, unsigned long nlen, char *text/*可以为NULL*/, unsigned long tlen/*可以为0*/);
```
- 给CXML节点添加属性
```c
int cxml_node_add_attr(CXML_NODE *cnode, char *key, unsigned long klen, char *val, unsigned long vlen);
```
- 给CXML节点添加节点
```c
int cxml_node_add_node(CXML_NODE *cnode, CXML_NODE *snode);
```
- 释放编码后的 **CXML** 信息
```c
int trash_cxml(CXML *v);
```
### 快捷操作宏 ###
**操作节点的宏:**
```c
// 用来定义一个 CXML_n 的结构来存储解码后的XML信息
CXML_FIELD_DEF(n)
// 中间使用 *aname 来定义一个节点名称, 前面的 * 不能省略
CXML_FIELD_DEF_END(n);
```
```c
// 用来声明函数,用来在其他的文件引入声明
CXML_FIELD_FUNC_DEF(n);
```
```c
// 上面的声明的实现文件
CXML_FIELD_FUNC(n)
// 存在多个节点,信息,就定义多行
// 第一个参数对应 XML的节点名称,大小写区分
// 第二个参数对应上面第一步 CXML_FIELD_DEF(n) 中定义的名称,去掉前缀 *
// 第三个参数对应第一个参数的字符个数
// 第四个参数可选 if 或者 elif 第一行必须为 if
CXML_FIELD_CMP(name, aname, l, e)
// 索引位置探头
// 第一个参数为 CXML_FIELD_DEF中定义的名称
// 第二个参数为 xml文件中处于父节点中子节点的索引位置,从零开始
// 第三个参数可选 if 或者 elif 第一行必须为if
CXML_FIELD_INDEX_CMP(aname, ik, e)
CXML_FIELD_FUNC_END();
```
操作节点属性的宏:
```c
// 用来定义一个 CXML_n 的结构来存储解码后的XML信息
CXML_ATTR_DEF(n)
// 中间使用 *aname 来定义一个节点名称, 前面的 * 不能省略
CXML_ATTR_DEF_END(n);
```
```c
// 用来声明函数,用来在其他的文件引入声明
CXML_ATTR_FUNC_DEF(n);
```
```c
// 上面的声明的实现文件
CXML_ATTR_FUNC(n)
// 存在多个节点,信息,就定义多行
// 第一个参数对应 XML的节点名称,大小写区分
// 第二个参数对应上面第一步 CXML_FIELD_DEF(n) 中定义的名称,去掉前缀 *
// 第三个参数对应第一个参数的字符个数
// 第四个参数可选 if 或者 elif 第一行必须为 if
CXML_ATTR_CMP(name, aname, l, e)
// 索引位置探头
// 第一个参数为 CXML_FIELD_DEF中定义的名称
// 第二个参数为 xml文件中处于父节点中子节点的索引位置,从零开始
// 第三个参数可选 if 或者 elif 第一行必须为if
CXML_ATTR_INDEX_CMP(aname, ik, e)
CXML_ATTR_FUNC_END();
```
**两种宏的区别**在于第二个单词是 **ATTR** 或者 **FIELD**
如果**需要遍历某一个节点下的所有子节点**,可以使用如下宏:
```c
// 第一个参数为父节点的 data 属性
// 第二个参数为自定义的 CXML_NODE 元素的指针
CXML_LOOP_FREACH_DATA(data, cnode) {
// 这里访问 cnode 元素内容即可
// printf("%s:%s\n", cnode->key->s, cnode->sval->s);
}CXML_LOOP_FOREACH_END()
```
**遍历某一个子节点的所有的属性**信息,使用如下宏:
```c
// 第一个参数为需要遍历属性节点的 attrs
// 第二个参数为自定义的 CXML_ATTR 元素的指针
CXML_LOOP_FREACH_ATTR(attrs, attr) {
// 这里访问 attr 属性即可
printf("\t%s:%s\n", attr->key, attr->val);
} CXML_LOOP_FOREACH_END();
```
## 怎么快速在C语言或者C++操作XML? ##
**fastxml** 自定了一系列的宏,来方便操作XML文档,具体的示例可以在main.c中看到