Libxml2 是一个xml c语言版的解析器,本来是为Gnome项目开发的工具,是一个基于MIT License的免费开源软件。它除了支持c语言版以外,还支持c++、PHP、Pascal、Ruby、Tcl等语言的绑定,能在Windows、Linux、Solaris、MacOsX等平台上运行。功能还是相当强大的,相信满足一般用户需求没有任何问题。 本文主要简单介绍一下libxml2在linux下的C++使用的基础,操作系统为Ubuntu。
一、libxml2的安装
1、下载libxml2
地址ftp://xmlsoft.org/libxml2/,这里选择的是libxml2-2.8.0.tar.gz
2、解压
- tar zxvf libxml2-2.8.0.tar.gz
3、配置安装
- ./configure
- make
- sudo make install
4、安装libxml-dev
- sudo apt-get install libxml2-dev
5、把libxml2下的libxml拷贝一份到libxml2所在的目录
- sudo cp -r /usr/include/libxml2/libxml /usr/include/libxml
6、包含libxml2的测试程序在编译的时候需要引用xml2库,比如测试程序test.cpp,则在编译的时候应该:
二、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*类型
三、libxml2常用函数
int xmlKeepBlankDefault(int val); //设置是否忽略空白的节点,在解析之前一般要调用,默认值为0,最好设置成为1
xmlDocPtr xmlParseFile(const *filename); //分析一个xml文件,并返回一个xml文档的对象指针
xmlReadFile //读入一个带有某种编码的xml文档,并返回一个文档指针
xmlSaveFile //将文档以默认方式保存
xmlSaveFormatFileEnc //可将文档以某种编码/格式的方式进行保存
xmlFreeDoc //释放文档指针 注意:当调用此函数时,该文档所包含的所有节点内存都将被自动释放。一般来说,一个文档中所有的节点都应该动态分配然后加入文档,然后调用xmlFreeDoc函数一次性的释放所有节点动态分配的内存;但是当节点从文档中移除时,就需要调用xmlFreeNode或者是xmlFreeNodeList。
2、根节点相关函数
xmlNodePtr xmlDocGetRootElement(xmlDocPtr doc); //获得文档的根节点
xmlNodePtr xmlDocSetRootElement(xmlDocPtr doc, xmlNodePtr root); //设置文档的根节点
3、创建子节点相关函数
xmlNodePtr xmlNewNode(xmlNsPtr ns, const xmlChar *name); //创建一个新节点
xmlNodePtr xmlNewChild(xmlNodePtr parent, xmlNsPtr ns, const xmlChar *name, const xmlChar *content); // 创建一个新的字节点
xmlNodePtr xmlCopyNode(const xmlNodePtr curNode, int extended); //复制当前节点
xmlNodeSetContent //设置节点内容
xmlNodeGetContent //获取节点内容
xmlNodeListGetString //获取字符串
4、添加字节点相关函数
xmlNodePtr xmlAddChild(xmlNodePtr parent, xmlNodePtr curNode); //给指定的节点添加子节点
xmlNodePtr xmlAddNextSibling(xmlNodePtr curNode, xmlNodePtr brother); //添加兄弟节点到后面
xmlNodePtr xmlAddPrevSibling(xmlNodePtr curNode, xmlNodePtr brother); //添加兄弟节点到前面
xmlNodePtr xmlAddSibling(xmlNodePtr curNode, xmlNodePtr brother); //添加一个兄弟节点
5、属性相关函数
xmlAttrPtr xmlNewProp(xmlNodePtr curNode, const xmlChar *name, const xmlChar *value);//创建新节点属性
xmlAttrPtr xmlSetProp(xmlNodePtr curNode, const xmlChar *name, const xmlChar *value);//设置新节点属性
xmlAttrPtr *xmlGetProp(xmlNodePtr curNode, const xmlChar *name, const xmlChar *value);//读取节点属性
6、使用XPATH查找xml文档
使用XPATH的流程如下:
1、定义一个XPATH的上下文指针xmlXPathContextPtr context,并且使用函数xmlXPathNewContext来初始化该指针;
2、定义一个XPATH的对象指针xmlXPathObjectPtr obj,并使用函数xmlXPathEvalExpression来计算XPATH的表达式,得到查询结果,将结果存入对象指针当中;
3、使用obj->nodesetval得到节点集合指针,在其中包含了所有查询到的XPATH节点;
4、使用函数xmlXPathFreeContext来释放上下文指针;
5、最后使用函数xmlXPathFreeObject释放XPATH对象指针。
四、XML文件创建
- #include<iostream>
- #include<libxml/parser.h>
- #include<libxml/xpath.h>
- #include<libxml/tree.h>
-
- using namespace std;
-
- int main(){
- xmlDocPtr doc = xmlNewDoc(BAD_CAST"1.0");
- xmlNodePtr root_node = xmlNewNode(NULL,BAD_CAST"root");
- //set root node
- xmlDocSetRootElement(doc,root_node);
- //create nodes under root node
- xmlNewTextChild(root_node,NULL,BAD_CAST"IP",BAD_CAST"192.168.1.116");
- xmlNewTextChild(root_node,NULL,BAD_CAST"Port",BAD_CAST"65535");
- xmlNewTextChild(root_node,NULL,BAD_CAST"num",BAD_CAST"1000");
- //create a new node,set its content and attributes,then add it to root node
- xmlNodePtr node = xmlNewNode(NULL,BAD_CAST"node2");
- xmlNodePtr content = xmlNewText(BAD_CAST"NODE CONTENT");
- //add node to root node
- xmlAddChild(root_node,node);
- xmlAddChild(node,content);
- xmlNewProp(node,BAD_CAST"attribute",BAD_CAST"yes");
- //create a son node and a grandson one
- node = xmlNewNode(NULL,BAD_CAST"son");
- xmlAddChild(root_node,node);
- xmlNodePtr grandson = xmlNewNode(NULL,BAD_CAST"grandson");
- xmlAddChild(node,grandson);
- xmlAddChild(grandson,xmlNewText(BAD_CAST"This is a grandson node"));
- //save xml doc
- int ret = xmlSaveFile("create.xml",doc);
- if(ret != -1){
- cout<<"A xml doc is created;Write in "<<ret<<" bytes"<<endl;
- }
- xmlFreeDoc(doc);
- return 0;
- }
编译:g++ build.cc -lxml2
运行:打开create.xml
- <?xml version="1.0"?>
- <root>
- <IP>192.168.1.116</IP>
- <Port>65535</Port>
- <num>1000</num>
- <node2 attribute="yes">NODE CONTENT</node2>
- <son>
- <grandson>This is a grandson node</grandson>
- <son>
- </root>
五、XML文件解析
xml文件
- <?xml version="1.0"?>
- <root>
- <IP>192.168.1.116</IP>
- <Port>65535</Port>
- <num>1000</num>
- <node2 attribute="yes">NODE CONTENT</node2>
- <son>
- <grandson>This is a grandson node</grandson>
- <son>
- </root>
解析代码:
- #include<iostream>
- #include<libxml/parser.h>
- //#include<libxml/xmlmemory.h>
- #include<string>
-
- using namespace std;
-
- const char* xmlConfig="create.xml";
-
- int main(){
- xmlDocPtr doc;
- xmlNodePtr curNode;
- xmlChar* szKey;
-
- doc = xmlParseFile(xmlConfig);
- if(doc == NULL){
- cout<<"Document not parsed successfully!"<<endl;
- return -1;
- }
- //cout<<"Document parsed successfully!"<<endl;
- curNode = xmlDocGetRootElement(doc);
- if(curNode == NULL){
- cout<<"empty document.\n"<<endl;
- xmlFreeDoc(doc);
- return -1;
- }
- //cout<<"xmlDocGetRootElement OK.\n"<<endl;
- if(xmlStrcmp(curNode->name,BAD_CAST"root")){
- cerr<<"root node is not 'root'"<<endl;
- xmlFreeDoc(doc);
- return -1;
- }
- curNode = curNode->xmlChildrenNode;
- xmlNodePtr propNodePtr = curNode;
- while(NULL != curNode){
- if((!xmlStrcmp(curNode->name,(const xmlChar*)"IP"))){
- szKey = xmlNodeGetContent(curNode);
- cout<<"IP:"<<szKey<<endl;
- //string s((char*)szKey);
- xmlFree(szKey);
- //cout<<s<<endl;
- }else if((!xmlStrcmp(curNode->name,(const xmlChar*)"Port"))){
- szKey = xmlNodeGetContent(curNode);
- cout<<"Port:"<<szKey<<endl;
- xmlFree(szKey);
- }else if((!xmlStrcmp(curNode->name,(const xmlChar*)"num"))){
- szKey = xmlNodeGetContent(curNode);
- cout<<"num:"<<szKey<<endl;
- xmlFree(szKey);
- } else if((!xmlStrcmp(curNode->name,(const xmlChar*)"node2"))){
- szKey = xmlNodeGetContent(curNode);
- cout<<"node2:"<<szKey<<endl;
- xmlFree(szKey);
- // get attributes
- szKey = xmlGetProp(curNode,(const xmlChar*)"attribute");
- cout<<"node2->attribute:"<<szKey<<endl;
- xmlFree(szKey);
- }
- curNode= curNode->next;
- }
-
- return 0;
- }