前言
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),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,BAD_CAST "node2",NULL); node = xmlNewChild(one_node,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); fwrite(buf->content,buf->use,file); xmlUnlinkNode(one_node); xmlFreeNode(one_node); xmlBufferEmpty(buf); } const char* kRootEnd = "</ROOT>"; fwrite(kRootEnd,strlen(kRootEnd),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>
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对编程小技巧的支持。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。