今天弄了一天这东西,但只能解析第一层节点,当取第二层节点时返回的name为text,mygod!这和xml文件中的节点不一样啊,怎么会这样哩。。。。后来看了下面一篇文章总算明白了。每个节点的下一个子节点系统默认是空白文档!!!!需要使用一个xml函数忽略空白文档。。我用的libxml2是linux下自带的。编译时直接
g++ -o main xml_parser.c -lxml2 -I /usr/include/libxml2/ 就OK了。
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
(本篇内容接上一次的文章)在上次介绍完Libxml2在Linux下的安装和使用它来生成xml后,决定把如何使用Libxml2解析xml也一并拿出来和大家分享。 今天介绍的方法为使用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获取特定结点的内容(使用的xml文档见上面):
#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;
}
/* Load XML document */
doc = xmlParseFile(argv[1]);
if (doc == NULL)
{
cout<<"Error: unable to parse file: "<<argv[1]<<endl;
return -1;
}
/* Create xpath evaluation context */
xpathCtx = xmlXPathNewContext(doc);
if(xpathCtx == NULL)
{
cout<<"Error: unable to create new XPath context"<<endl;
xmlXPathFreeContext(xpathCtx);
xmlFreeDoc(doc);
return -2;
}
xpathExpr="/root/node3";
/* Evaluate xpath expression */
xpathObj = xmlXPathEvalExpression((const xmlChar*)(xpathExpr.c_str()), xpathCtx);
if(xpathObj == NULL)
{
cout<<"Error: unable to evaluate xpath expression"<<xpathExpr<<endl;
xmlXPathFreeContext(xpathCtx);
xmlFreeDoc(doc);
return -3;
}
/* get values of the selected nodes */
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);
/* free the document */
xmlFreeDoc(doc);
xmlCleanupParser();
return 0;
}
所有程序编译运行都同前一次所说,这里不再一一例举。
另外由于这个排版比较麻烦,所以程序美观程度大打折扣,大家就将就一下吧,呵呵。
http://hi.baidu.com/bwgm/blog/item/28b19fb1109e0f5409230298.html