您好,欢迎访问三七文档
C++的XML编程经验――LIBXML2库使用指南写这篇文章的原因有如下几点:1)C++标准库中没有操作XML的方法,用C++操作XML文件必须熟悉一种函数库,LIBXML2是其中一种很优秀的XML库,而且它同时支持多种编程语言;2)LIBXML2库的Tutorial写得不太好,尤其是编码转换的部分,不适用于中文编码的转换;3)网上的大多数关于Libxml2的介绍仅仅是翻译了自带的资料,没有详细介绍如何在windows平台下进行编程,更很少提到如何解决中文问题。基于以上几点原因,决定写一个在Windows平台下,使用C/C++语言,应用LibXml2库来进行xml文档操作,同时使用ICONV库进行中文编码转换的文档。其中还涉及了Makefile、XPATH等相关内容。本文中所有的源代码在。1.下载与安装LIBXML2和ICONVLibxml2是一个C语言的XML程序库,可以简单方便的提供对XML文档的各种操作,并且支持XPATH查询,以及部分的支持XSLT转换等功能。Libxml2的下载地址是,完全版的库是开源的,并且带有例子程序和说明文档。最好将这个库先下载下来,因为这样可以查看其中的文档和例子。windows版本的的下载地址是;这个版本只提供了头文件、库文件和dll,不包含源代码、例子程序和文档。在文本中,只需要下载libxml2库、iconv库和zlib库就行了(注意,libxml2库依赖iconv和zlib库,本文中重点关注libxml2和iconv,zlib不介绍),我使用的版本是libxml2-2.6.30.win32.zip、zlib-1.2.3.win32.zip和iconv-1.9.2.win32.zip。在编程的时候,我们使用windows版本的libxml2、zlib和iconv,将其解压缩到指定文件夹,例如D:libxml2-2.6.30.win32,D:zlib-1.2.3.win32以及D:iconv-1.9.2.win32。事实上,我们知道在windows下面使用头文件、库文件和dll是不需要安装的,它又没有使用任何需要注册的组件或者数据库,只需要告诉编译器和链接器这些资源的位置就可以了。注意:要在path变量中加上D:iconv-1.9.2.win32bin;D:zlib-1.2.3.win32bin;D:libxml2-2.6.30.win32bin这三个地址,否则在执行的时候就找不到。或者使用更简单的方法,把其中的三个dll到拷贝到system32目录中。有两种方法来编译链接基于libxml2的程序,第一种是在VC环境中设置lib和include路径,并在link设置中添加libxml2.lib和iconv.lib;第二种是用编译器选项告诉编译器cl.exe头文件的位置,并用链接器选项告诉链接器link.exe库文件的位置,同时在windows环境变量path中添加libxml2中bin文件夹的位置,以便于程序运行时可以找到dll(也可以将dll拷贝到system32目录下)。显然我选择了第二种,那么编译链接一个名为CreateXmlFile.cpp源文件的命令如下:cl/c/ID:iconv-1.9.2.win32include/ID:libxml2-2.6.30.win32includeCreateXmlFile.cpplink/libpath:D:iconv-1.9.2.win32lib/libpath:D:libxml2-2.6.30.win32libCreateXmlFile.objiconv.liblibxml2.lib显然这样很费时,那么再不用makefile就显得矫情了,于是,一个典型的使用nmake.exe(VC自带的makefile工具)的文件如下:MAKEFILE##本目录下所有源代码的makefile,使用方法是nmakeTARGET_NAME=源代码文件名字(不加后缀)#例如nmakeTARGET_NAME=CreateXmlFile#Author:WangXuebin##Flags-编译debug版本##指定要使用的库的路径,需要用户修改的变量一般放在makefile文件的最上面LIBXML2_HOME=D:libxml2-2.6.30.win32ICONV_HOME=D:iconv-1.9.2.win32#指定编译器选项,/c表明cl命令只编译不链接;/MTd表明使用多线程debug库;/Zi表明产生完整的调试信息;#/Od表明关闭编译优化;/D_DEBUG表明定义一个名为_DEBUG的宏CPP_FLAGS=/c/MTd/Zi/Od/D_DEBUG#链接选项,/DEBUG表明创建Debug信息EXE_LINK_FLAGS=/DEBUG#指定链接的库LIBS=iconv.liblibxml2.lib#指定编译路径选项,链接路径选项INCLUDE_FLAGS=/I$(LIBXML2_HOME)include/I$(ICONV_HOME)includeLIB_PATH_FLAGS=/libpath:$(ICONV_HOME)lib/libpath:$(LIBXML2_HOME)lib###################################################Targets目标#$(TARGET_NAME):$(TARGET_NAME).execlean:$(TARGET_NAME).exe$(TARGET_NAME).obj:$(TARGET_NAME).cppcl$(CPP_FLAGS)$(INCLUDE_FLAGS)$(TARGET_NAME).cpp$(TARGET_NAME).exe:$(TARGET_NAME).objlink$(EXE_LINK_FLAGS)$(LIB_PATH_FLAGS)$(TARGET_NAME).obj$(LIBS)clean:$(TARGET_NAME).exedel$(TARGET_NAME).exedel$(TARGET_NAME).objdel$(TARGET_NAME).ilkdel$(TARGET_NAME).pdb本文不准备介绍makefile的写法,但后续例子程序的编译链接依葫芦画瓢都没有问题,执行编译链接的命令如下:nmakeTARGET_NAME=CreateXmlFile执行清理的命令如下:nmakeTARGET_NAME=CreateXmlFileclean2.Libxml2中的数据类型和函数一个函数库中可能有几百种数据类型以及几千个函数,但是记住大师的话,90%的功能都是由30%的内容提供的。对于libxml2,我认为搞懂以下的数据类型和函数就足够了。2.1内部字符类型xmlCharxmlChar是Libxml2中的字符类型,库中所有字符、字符串都是基于这个数据类型。事实上它的定义是:xmlstring.htypedefunsignedcharxmlChar;使用unsignedchar作为内部字符格式是考虑到它能很好适应UTF-8编码,而UTF-8编码正是libxml2的内部编码,其它格式的编码要转换为这个编码才能在libxml2中使用。还经常可以看到使用xmlChar*作为字符串类型,很多函数会返回一个动态分配内存的xmlChar*变量,使用这样的函数时记得要手动删除内存。2.2xmlChar相关函数如同标准c中的char类型一样,xmlChar也有动态内存分配、字符串操作等相关函数。例如xmlMalloc是动态分配内存的函数;xmlFree是配套的释放内存函数;xmlStrcmp是字符串比较函数等等。基本上xmlChar字符串相关函数都在xmlstring.h中定义;而动态内存分配函数在xmlmemory.h中定义。2.3xmlChar*与其它类型之间的转换另外要注意,因为总是要在xmlChar*和char*之间进行类型转换,所以定义了一个宏BAD_CAST,其定义如下:xmlstring.h#defineBAD_CAST(xmlChar*)原则上来说,unsignedchar和char之间进行强制类型转换是没有问题的。2.4文档类型xmlDoc、指针xmlDocPtrxmlDoc是一个struct,保存了一个xml的相关信息,例如文件名、文档类型、子节点等等;xmlDocPtr等于xmlDoc*,它搞成这个样子总让人以为是智能指针,其实不是,要手动删除的。xmlNewDoc函数创建一个新的文档指针。xmlParseFile函数以默认方式读入一个UTF-8格式的文档,并返回文档指针。xmlReadFile函数读入一个带有某种编码的xml文档,并返回文档指针;细节见libxml2参考手册。xmlFreeDoc释放文档指针。特别注意,当你调用xmlFreeDoc时,该文档所有包含的节点内存都被释放,所以一般来说不需要手动调用xmlFreeNode或者xmlFreeNodeList来释放动态分配的节点内存,除非你把该节点从文档中移除了。一般来说,一个文档中所有节点都应该动态分配,然后加入文档,最后调用xmlFreeDoc一次释放所有节点申请的动态内存,这也是为什么我们很少看见xmlNodeFree的原因。xmlSaveFile将文档以默认方式存入一个文件。xmlSaveFormatFileEnc可将文档以某种编码/格式存入一个文件中。2.5节点类型xmlNode、指针xmlNodePtr节点应该是xml中最重要的元素了,xmlNode代表了xml文档中的一个节点,实现为一个struct,内容很丰富:tree.htypedefstruct_xmlNodexmlNode;typedefxmlNode*xmlNodePtr;struct_xmlNode{void*_private;/*applicationdata*/xmlElementTypetype;/*typenumber,mustbesecond!*/constxmlChar*name;/*thenameofthenode,ortheentity*/struct_xmlNode*children;/*parent-childslink*/struct_xmlNode*last;/*lastchildlink*/struct_xmlNode*parent;/*child-parentlink*/struct_xmlNode*next;/*nextsiblinglink*/struct_xmlNode*prev;/*previoussiblinglink*/struct_xmlDoc*doc;/*thecontainingdocument*//*Endofcommonpart*/xmlNs*ns;/*pointertotheassociatednamespace*/xmlChar*content;/*thecontent*/struct_xmlAttr*properties;/*propertieslist*/xmlNs*nsDef;/*namespacedefinitionsonthisnode*/void*psvi;/*fortype/PSVIinformations*/unsignedshortline;/*linenumber*/unsignedshortextra;/*extradataforXPath/XSLT*/};可以看到,节点之间是以链表和树两种方式同时组织起来的,next和prev指针可以组成链表,而parent和children可以组织为树。同时还有以下重要元素:节点中的文字内容:content;节点所属文档:doc;节点名字:name;节点的namespace:ns;
本文标题:libxml2教程
链接地址:https://www.777doc.com/doc-2880758 .html