1 Star 0 Fork 23

PerryHu / fastxml

forked from Josin / fastxml 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
README.md 6.24 KB
一键复制 编辑 原始数据 按行查看 历史
liqiongfan 提交于 2019-07-20 11:25 . 提交版本1.0

fastxml 纯C语言编写的XML解析库

什么是fastxml?

fastxml是一款支持XML解析的多根节点的解析引擎,支持特性如下:

  • 支持多根 XML,一个 XML 文档支持多个 ROOT 标记,如下包含informationlist

    <?xml version="1.0" encoding="UTF-8"?>
    <information>
      <name>Josin</name>
      <age>26</age>
      <address>Changsha</address>
    </information>
    
    <list>
    	<name>Linux</name>
    	<version>v5.0.1</version>
    	<tool>Git</tool>
    </list>
  • 支持单一元素直接闭合语法

    <?xml version="1.0" encoding="UTF-8"?>
    <information>
      <name>Josin</name>
      <age>26</age>
      <address>Changsha</address>
      <other_info/><!--直接闭合-->
    </information>
  • 支持XML文档声明,声明必须位于第一行,以及众多属性,标准的XML声明如下:

    <?xml version="1.0" encoding="UTF-8" author="Josin"?>
  • 支持标记的属性特性,如下面的 information 标记包含的 idpid 属性:

    <?xml version="1.0" encoding="UTF-8"?>
    <information id="11" pid="99">
        <name>Josin</name>
        <age>26</age>
        <address>Changsha</address>
    </information>
  • 支持注释注意:注释不可以嵌套

    <?xml version="1.0" encoding="UTF-8"?>
    <information id="11" pid="99">
        <!--<name>Josin</name>-->
        <age>2<!--6--></age>
        <address>Changsha</address>
    </information>
  • 支持 CDATA标记 防止浏览器转义

    <?xml version="1.0" encoding="UTF-8" author="Josin"?>
    <!--This is the comments-->
    <information>
        <name><![CDATA[Josin]]></name>
        <!--<age>26</age>-->
        <address>Hunan</address>
    </information>
  • 暂不支持特性:DTD规则以及校验

编译 & 运行

fastxml 使用纯C99语法编写,可以使用在支持标准C99的操作系统上,fastxml使用 cmake编译管理系统,推荐版本 3.13以及以上

git clone https://gitee.com/josinli/fastxml.git
cd fastxml
mkdir build
cd build
cmake .. && make 
./fastxml 

性能测试

性能测试基准平台:MacBook ProLinux 平台性能更高, 解析大约22KB 的 XML 文档 1100 次耗时 1 秒

APIs 列表

  • 从字符串解析 XML,返回 NULL 表示XML文件格式错误
CXML *new_cxml_from_string2(char *str, unsigned long long);
  • 从CXML中编码为字符串,返回的字符串需要通过 free 函数释放
char *new_string_from_cxml(CXML *c);
  • 获取解码 XML 的错误信息
char  *new_cxml_get_error();
  • 生成CXML对象
CXML *cxml_new_cxml(char *tag, char *version, char *encoding);	
  • 给CXML对象添加根节点
int cxml_add_root_node(CXML *xml, CXML_NODE *node);
  • 生成CXML节点信息
CXML_NODE *cxml_make_node(char *name, unsigned long nlen, char *text/*可以为NULL*/, unsigned long tlen/*可以为0*/);
  • 给CXML节点添加属性
int cxml_node_add_attr(CXML_NODE *cnode, char *key, unsigned long klen, char *val, unsigned long vlen);
  • 给CXML节点添加节点
int cxml_node_add_node(CXML_NODE *cnode, CXML_NODE *snode);
  • 释放编码后的 CXML 信息
int   trash_cxml(CXML *v);

快捷操作宏

操作节点的宏:

// 用来定义一个 CXML_n 的结构来存储解码后的XML信息
CXML_FIELD_DEF(n)
// 中间使用 *aname 来定义一个节点名称, 前面的 * 不能省略
CXML_FIELD_DEF_END(n);
// 用来声明函数,用来在其他的文件引入声明
CXML_FIELD_FUNC_DEF(n);
// 上面的声明的实现文件
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();

操作节点属性的宏:

// 用来定义一个 CXML_n 的结构来存储解码后的XML信息
CXML_ATTR_DEF(n)
// 中间使用 *aname 来定义一个节点名称, 前面的 * 不能省略
CXML_ATTR_DEF_END(n);
// 用来声明函数,用来在其他的文件引入声明
CXML_ATTR_FUNC_DEF(n);
// 上面的声明的实现文件
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

如果需要遍历某一个节点下的所有子节点,可以使用如下宏:

// 第一个参数为父节点的 data 属性
// 第二个参数为自定义的 CXML_NODE 元素的指针
CXML_LOOP_FREACH_DATA(data, cnode) {
	  // 这里访问 cnode 元素内容即可
    // printf("%s:%s\n", cnode->key->s, cnode->sval->s);
}CXML_LOOP_FOREACH_END()

遍历某一个子节点的所有的属性信息,使用如下宏:

// 第一个参数为需要遍历属性节点的 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中看到

C
1
https://gitee.com/Perry0531/fastxml.git
git@gitee.com:Perry0531/fastxml.git
Perry0531
fastxml
fastxml
master

搜索帮助