Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1212147
  • 博文数量: 261
  • 博客积分: 4196
  • 博客等级: 上校
  • 技术积分: 3410
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-17 17:05
文章分类

全部博文(261)

文章存档

2018年(1)

2017年(22)

2016年(2)

2015年(8)

2014年(27)

2013年(40)

2012年(161)

分类: LINUX

2012-04-18 15:57:52

from:http://hi.baidu.com/goggle1/blog/item/5a381ef2cca48dc00a46e0d5.html
ibxml2
1 声明指针:                              文档指针(xmlDocPtr),结点指针(xmlNodePtr);
2 得到文档doc:         xmlReadFile
3 得到根结点root_node: xmlDocGetRootElement
4 结点操作:
1)获得到结点值:                 xmlNodeGetContent(对应于xmlFree)
2)遍历:
指向下一个结点:           xmlNodePtr ->children
结点值:                            xmlNodePtr->name,
结点内遍历:                   xmlNodePtr->next
5 释放内存:                            xmlFreeDoc,xmlFree

今天介绍的方法为使用Dom树解析,将给出两个实例,说明如何使用Libxml2遍历xml文档和使Xpath获取特定结点的内容值:
程序使用的xml文档为:


content of node 1
node has attributes
other way to create content


遍历程序代码:
#include
#include
#include
using namespace std;

int main(int argc,char** argv)
{
xmlDocPtr doc=NULL;
xmlNodePtr cur=NULL;
char* name=NULL;
char* value=NULL;

xmlKeepBlanksDefault (0);

if(argc<2)
{
cout<<"argc must be 2 or above."< return -1;
}

doc=xmlParseFile(argv[1]);//创建Dom树
if(doc==NULL)
{
cout<<"Loading xml file failed."< exit(1);
}

cur=xmlDocGetRootElement(doc);//获取根节点
if(cur==NULL)
{
cout<<"empty file"< xmlFreeDoc(doc);
exit(2);
}

//walk the tree
cur=cur->xmlChildrenNode;//get sub node
while(cur !=NULL)
{
name=(char*)(cur->name);
value=(char*)xmlNodeGetContent(cur);
cout<<"name is: "< xmlFree(value);
cur=cur->next;
}

xmlFreeDoc(doc);//释放xml解析库所用资源
xmlCleanupParser();
return 0;
}

说明:
1. 当使用dom树来解析xml文档时,由于默认的方式是把节点间的空白当作第一个子节 点,所以为了能和常说的第一个子节点相符,需调用xmlKeepBlanksDefault (0)函数来忽略这种空白。
2. 对于使用xmlChar* xmlNodeGetContent(xmlNodePtr cur)函数获取节点内容后,必须调用xmlFree()来对所分配的内存进行释放。

使用Xpath获取特定结点的内容:
#include
#include
using namespace std;

#include
#include
#include
#include

int main(int argc,char** argv)
{
xmlDocPtr doc;
xmlXPathContextPtr xpathCtx;
xmlXPathObjectPtr xpathObj;
xmlNodeSetPtr nodeset;
string xpathExpr;
char* val=NULL;
int size,i;

if(argc<2)
{
cout<<"argc must be 2 or above."< return -1;
}

doc = xmlParseFile(argv[1]);
if (doc == NULL)
{
cout<<"Error: unable to parse file: "< return -1;
}

xpathCtx = xmlXPathNewContext(doc);
if(xpathCtx == NULL)
{
cout<<"Error: unable to create new XPath context"< xmlXPathFreeContext(xpathCtx);
xmlFreeDoc(doc);
return -2;
}

xpathExpr="/root/node3";
xpathObj = xmlXPathexpression_r_r((const xmlChar*)(xpathExpr.c_str()), xpathCtx);
if(xpathObj == NULL)
{
cout<<"Error: unable to uate xpath expression_r_r"< xmlXPathFreeContext(xpathCtx);
xmlFreeDoc(doc);
return -3;
}

nodeset=xpathObj->nodesetval;
if(xmlXPathNodeSetIsEmpty(nodeset))
{
cout<<"No such nodes."< xmlXPathFreeObject(xpathObj);
xmlXPathFreeContext(xpathCtx);
xmlFreeDoc(doc);
return -4;
}

//get the value  
size = (nodeset) ? nodeset->nodeNr : 0;
for(i = 0; i {
val=(char*)xmlNodeListGetString(doc, nodeset->nodeTab[i]->xmlChildrenNode, 1);      
cout<<"the results are: "< xmlFree(val);
}

//Cleanup of XPath data
xmlXPathFreeObject(xpathObj);
xmlXPathFreeContext(xpathCtx); 

xmlFreeDoc(doc);
xmlCleanupParser();
return 0;
}

我在使用的过程中,犯了错误,没有使用xmlFree(val),也没有使用xmlCleanupParser(),当然更没有使用xmlKeepBlanksDefault (0);最后还是使用了valgrind来定位内存泄露问题!

提示:
xmlCleanupParser()
不要调用两次,否则就会出现coredump;
# gdb -c core.18659
... ...
Program terminated with signal 6, Aborted.
... ...
(gdb) bt
#0  0x0000003aeec30265 in ?? ()
#1  0x0000003aeec31d10 in ?? ()
... ...
bt也看不到任何有用的信息。其实只是内存的重复释放造成!

我的总结:在 一个程序(是程序不是文件)中,从头到尾只要出现一次    xmlCleanupParser();    xmlMemoryDump();这两个函数。也就是说要在你用完libxml2之后确定不要再调用它的相关函数才调用这两个函数收回资源,否则会出现内存泄漏。

阅读(6698) | 评论(0) | 转发(0) |
0

上一篇:线程编程

下一篇:fopen和open有什么区别?

给主人留下些什么吧!~~