温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

C/C++利用libxml2高效输出XML大文件详解

发布时间:2020-09-18 00:40:54 来源:脚本之家 阅读:253 作者:infoworld 栏目:编程语言

前言

Libxml2 是一个xml c语言版的解析器,本来是为Gnome项目开发的工具,是一个基于MIT License的免费开源软件。它除了支持c语言版以外,还支持c++、PHP、Pascal、Ruby、Tcl等语言的绑定,能在Windows、Linux、Solaris、MacOsX等平台上运行。功能还是相当强大的,相信满足一般用户需求没有任何问题。

libxml2常用数据类型

xmlChar是libxml2中的字符类型,在库中的所有字符,字符串都是基于这个数据类型的。

xmlChar*是指针类型,很多函数都会返回一个动态分配的内存的xmlChar*类型的变量,因此,在使用这类函数时要记得释放内存,否则会导致内存泄漏,例如这样的用法:

xmlChar *name = xmlNodeGetContent(CurNode);
strcpy(data.name, name);
xmlFree(name);
  • xmlDoc、 xmlDocPtr //文档对象结构体及指针
  • xmlNode、 xmlNodePtr //节点对象结构体及节点指针
  • xmlAttr、 xmlAttrPtr //节点属性的结构体及其指针
  • xmlNs、 xmlNsPtr //节点命名空间的结构及指针
  • BAD_CAST //一个宏定义,事实上它即是xmlChar*类型

场景

1.libxml2基本上算是xml的C/C++标准读写库. 在linux,macOS里是默认支持. 可惜在Windows上有自己专有的msxml, 所以并不支持libxml2, 恶心的是msxml还不是标配, 还要必须另外下载安装, 所以作为Windows上优先选择的XML库, 就是可跨平台的libxml2.

2.xml的sax读取库expat也是比较优秀的选择, 可惜不支持写.

3.一般的写库方式是生成一整个DOM结构, 之后把这个DOM结构输出到XML格式的文本里, 可调用自带写函数或标准io函数. 这样的缺点是如果生成这个DOM结构过于大, 会导致在生成这个DOM结构时内存暴涨,之后再输出到内存里,这时候内存又暴涨一次,最后从内存输出到文件里.

说明

1.DOM结构存储非常浪费内存, 如果数据量大时, 但是元素的父子关系, 文本值,属性值等等很浪费内存. 如果我们可以按照每个元素来输出的话,最好输出完就释放元素内存, 那么能最大限度的利用内存资源.

2.局部输出元素可以最大限度使用系统的资源, 比如IO输出需要权限限制的函数, 或者输出到界面等

例子

以下例子是windows上使用libxml2, 用mingw编译出的libxml2, 使用_wfopen来打开unicode编码的文件路径.

#include "stdafx.h"
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/xmlreader.h>
#include <iostream>
#include <memory>

void TestStandardIOForXml()
{
 xmlDocPtr doc = NULL; /* document pointer */
 xmlNodePtr one_node = NULL, node = NULL, node1 = NULL;/* node pointers */
 char buff[256];
 int i, j;

 doc = xmlNewDoc(BAD_CAST "1.0");
 std::shared_ptr<void> sp_doc(doc,[](void* doc1){
 xmlDocPtr doc = (xmlDocPtr)doc1;
 xmlFreeDoc(doc);
 });

 FILE* file = _wfopen(L"test.xml",L"wb");
 if(!file)
 return;

 std::shared_ptr<FILE> sp_file(file,[](FILE* file){
 fclose(file);
 });

 // 写XML的声明
 xmlChar* doc_buf = NULL;
 int size = 0;
 xmlDocDumpMemoryEnc(doc,&doc_buf,&size,"UTF-8");
 std::shared_ptr<xmlChar> sp_xc(doc_buf,[](xmlChar* doc_buf){
 xmlFree(doc_buf);
 });
 fwrite(doc_buf,strlen((const char*)doc_buf),1,file);
 xmlBufferPtr buf = xmlBufferCreate();
 std::shared_ptr<void> sp_buf(buf,[](void* buf1){
 xmlBufferPtr buf = (xmlBufferPtr)buf1;
 xmlBufferFree(buf);
 });

 const char* kRootBegin = "<ROOT>";
 fwrite(kRootBegin,strlen(kRootBegin),1,file);
 for(int i = 0; i< 10; ++i){
 one_node = xmlNewNode(NULL, BAD_CAST "one");
 xmlNewChild(one_node, NULL, BAD_CAST "node1",
  BAD_CAST "content of node 1");
 xmlNewChild(one_node, NULL, BAD_CAST "node2", NULL);
 node = xmlNewChild(one_node, NULL, BAD_CAST "node3",BAD_CAST "this node has attributes");
 xmlNewProp(node, BAD_CAST "attribute", BAD_CAST "yes");
 xmlNewProp(node, BAD_CAST "foo", BAD_CAST "bar");

 node = xmlNewNode(NULL, BAD_CAST "node4");
 node1 = xmlNewText(BAD_CAST "other way to create content (which is also a node)");
 xmlAddChild(node, node1);
 xmlAddChild(one_node, node);

 xmlNodeDump(buf,doc,one_node,1,1);
 fwrite(buf->content,buf->use,1,file);

 xmlUnlinkNode(one_node);
 xmlFreeNode(one_node);
 xmlBufferEmpty(buf);
 }

 const char* kRootEnd = "</ROOT>";
 fwrite(kRootEnd,strlen(kRootEnd),1,file);

}

输出文件:

<?xml version="1.0" encoding="UTF-8"?>
<ROOT><one>
 <node1>contentÖÐÎÄ of node 1</node1>
 <node2/>
 <node3 attribute="yes" foo="bar">this node has attributes</node3>
 <node4>other way to create content (which is also a node)</node4>
 </one><one>
 <node1>content of node 1</node1>
 <node2/>
 <node3 attribute="yes" foo="bar">this node has attributes</node3>
 <node4>other way to create content (which is also a node)</node4>
 </one><one>
 <node1>content of node 1</node1>
 <node2/>
 <node3 attribute="yes" foo="bar">this node has attributes</node3>
 <node4>other way to create content (which is also a node)</node4>
 </one><one>
 <node1>content of node 1</node1>
 <node2/>
 <node3 attribute="yes" foo="bar">this node has attributes</node3>
 <node4>other way to create content (which is also a node)</node4>
 </one><one>
 <node1>content of node 1</node1>
 <node2/>
 <node3 attribute="yes" foo="bar">this node has attributes</node3>
 <node4>other way to create content (which is also a node)</node4>
 </one><one>
 <node1>content of node 1</node1>
 <node2/>
 <node3 attribute="yes" foo="bar">this node has attributes</node3>
 <node4>other way to create content (which is also a node)</node4>
 </one><one>
 <node1>content of node 1</node1>
 <node2/>
 <node3 attribute="yes" foo="bar">this node has attributes</node3>
 <node4>other way to create content (which is also a node)</node4>
 </one><one>
 <node1>content of node 1</node1>
 <node2/>
 <node3 attribute="yes" foo="bar">this node has attributes</node3>
 <node4>other way to create content (which is also a node)</node4>
 </one><one>
 <node1>content of node 1</node1>
 <node2/>
 <node3 attribute="yes" foo="bar">this node has attributes</node3>
 <node4>other way to create content (which is also a node)</node4>
 </one><one>
 <node1>content of node 1</node1>
 <node2/>
 <node3 attribute="yes" foo="bar">this node has attributes</node3>
 <node4>other way to create content (which is also a node)</node4>
 </one></ROOT>

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对亿速云的支持。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI