前言
Libxml2 是一个xml c语言版的解析器,本来是为Gnome项目开发的工具,是一个基于MIT License的免费开源软件。它除了支持c语言版以外,还支持c++、PHP、Pascal、Ruby、Tcl等语言的绑定,能在Windows、Linux、Solaris、MacOsX等平台上运行。功能还是相当强大的,相信满足一般用户需求没有任何问题。
libxml2常用数据类型
xmlChar是libxml2中的字符类型,在库中的所有字符,字符串都是基于这个数据类型的。
xmlChar*是指针类型,很多函数都会返回一个动态分配的内存的xmlChar*类型的变量,因此,在使用这类函数时要记得释放内存,否则会导致内存泄漏,例如这样的用法:
1
2
3
|
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编码的文件路径.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
#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 );
}
|
输出文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
<?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>
|
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对服务器之家的支持。
原文链接:http://blog.csdn.net/infoworld/article/details/78577150