libxml2
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文档为: <?xml version="1.0" encoding="UTF-8"?> <root> <node1>content of node 1</node1> <node3 attribute="yes">node has attributes</node3> <node4>other way to create content</node> </root> 遍历程序代码: #include <iostream> #include <libxml/parser.h> #include <libxml/tree.h> 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."<<endl; return -1; } doc=xmlParseFile(argv[1]);//创建Dom树 if(doc==NULL) { cout<<"Loading xml file failed."<<endl; exit(1); } cur=xmlDocGetRootElement(doc);//获取根节点 if(cur==NULL) { cout<<"empty file"<<endl; 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: "<<name<<", value is: "<<value<<endl; xmlFree(value); cur=cur->next; } xmlFreeDoc(doc);//释放xml解析库所用资源 xmlCleanupParser(); return 0; } 说明: 1. 当使用dom树来解析xml文档时,由于默认的方式是把节点间的空白当作第一个子节 点,所以为了能和常说的第一个子节点相符,需调用xmlKeepBlanksDefault (0)函数来忽略这种空白。 2. 对于使用xmlChar* xmlNodeGetContent(xmlNodePtr cur)函数获取节点内容后,必须调用xmlFree()来对所分配的内存进行释放。 使用Xpath获取特定结点的内容: #include <iostream> #include <string> using namespace std; #include <libxml/tree.h> #include <libxml/parser.h> #include <libxml/xpath.h> #include <libxml/xpathInternals.h> 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."<<endl; return -1; } doc = xmlParseFile(argv[1]); if (doc == NULL) { cout<<"Error: unable to parse file: "<<argv[1]<<endl; return -1; } xpathCtx = xmlXPathNewContext(doc); if(xpathCtx == NULL) { cout<<"Error: unable to create new XPath context"<<endl; 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"<<xpathExpr<<endl; xmlXPathFreeContext(xpathCtx); xmlFreeDoc(doc); return -3; } nodeset=xpathObj->nodesetval; if(xmlXPathNodeSetIsEmpty(nodeset)) { cout<<"No such nodes."<<endl; xmlXPathFreeObject(xpathObj); xmlXPathFreeContext(xpathCtx); xmlFreeDoc(doc); return -4; } //get the value size = (nodeset) ? nodeset->nodeNr : 0; for(i = 0; i <size; i++) { val=(char*)xmlNodeListGetString(doc, nodeset->nodeTab[i]->xmlChildrenNode, 1); cout<<"the results are: "<<val<<endl; 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 ?? () |