xml解析器tinyXML
转自:http://blog.163.com/kin_jiezi/blog/static/3683682201172593616285/ 读取和设置xml配置文件是最常用的操作,试用了几个C++的XML解析器,个人感觉TinyXML是使用起来最舒服的,因为它的API接口和Java的十分类似,面向对象性很好。 TinyXML是一个开源的解析XML的解析库,能够用于C++,能够在Windows或Linux中编译。这个解析库的模型通过解析XML文件,然后在内存中生成DOM模型,从而让我们很方便的遍历这棵XML树。 DOM模型即文档对象模型,是将整个文档分成多个元素(如书、章、节、段等),并利用树型结构表示这些元素之间的顺序关系以及嵌套包含关系。 如下是一个XML片段:
<
Persons
>
Person ID ="1" name >周星星 </ age >20 Person ="2" >白晶晶 >18 > 在TinyXML中,根据XML的各种元素来定义了一些类: TiXmlBase:整个TinyXML模型的基类。 TiXmlAttribute:对应于XML中的元素的属性。 TiXmlNode:对应于DOM结构中的节点。 TiXmlComment:对应于XML中的注释 TiXmlDeclaration:对应于XML中的申明部分,即<?versiong="1.0"?>。 TiXmlDocument:对应于XML的整个文档。 TiXmlElement:对应于XML的元素。 TiXmlText:对应于XML的文字部分 TiXmlUnknown:对应于XML的未知部分。 TiXmlHandler:定义了针对XML的一些操作。 TinyXML是个解析库,主要由DOM模型类(TiXmlBase、TiXmlNode、TiXmlAttribute、TiXmlComment、TiXmlDeclaration、TiXmlElement、TiXmlText、TiXmlUnknown)和操作类(TiXmlHandler)构成。它由两个头文件(.h文件)和四个CPP文件(.cpp文件)构成,用的时候,只要将(tinyxml.h、tinystr.h、tinystr.cpp、tinyxml.cpp、tinyxmlerror.cpp、tinyxmlparser.cpp)导入工程就可以用它的东西了。如果需要,可以将它做成自己的DLL来调用。举个例子就可以说明一切。。。 对应的XML文件:
>phinecos
>22
>
读写XML文件的程序代码:
#include<iostream>
#include " tinyxml.h " #include tinystr.h " #include< string> #include<windows.h> #include<atlstr.h> using namespacestd; CStringGetAppPath() {//获取应用程序根目录 TCHARmodulePath[MAX_PATH]; GetModuleFileName(NULL,modulePath,MAX_PATH); CStringstrModulePath(modulePath); strModulePath=strModulePath.Left(strModulePath.ReverseFind(_T(''))); returnstrModulePath; } boolCreateXmlFile( string&szFileName) {创建xml文件,szFilePath为文件保存的路径,若创建成功返回true,否则false try { 创建一个XML的文档对象。 TiXmlDocument*myDocument=newTiXmlDocument(); 创建一个根元素并连接。 TiXmlElement*RootElement=newTiXmlElement("Persons"); myDocument->LinkEndChild(RootElement); 创建一个Person元素并连接。 TiXmlElement*PersonElement=Person"); RootElement->LinkEndChild(PersonElement); 设置Person元素的属性。 PersonElement->SetAttribute(ID",1"); 创建name元素、age元素并连接。 TiXmlElement*NameElement=name"); TiXmlElement*AgeElement=age"); PersonElement->LinkEndChild(NameElement); PersonElement->LinkEndChild(AgeElement); 设置name元素和age元素的内容并连接。 TiXmlText*NameContent=newTiXmlText(周星星"); TiXmlText*AgeContent=22"); NameElement->LinkEndChild(NameContent); AgeElement->LinkEndChild(AgeContent); CStringappPath=GetAppPath(); stringseperator="; stringfullPath=appPath.GetBuffer(0)+seperator+szFileName; myDocument->SaveFile(fullPath.c_str());保存到文件 } catch(string&e) { returnfalse; } true; } boolReadXmlFile( string&szFileName) {读取Xml文件,并遍历try { CStringappPath=GetAppPath(); 0)+seperator+szFileName; newTiXmlDocument(fullPath.c_str()); myDocument->LoadFile(); 获得根元素,即Persons。 TiXmlElement*RootElement=myDocument->RootElement(); 输出根元素名称,即输出Persons。 cout<<RootElement->Value()<<endl; 获得第一个Person节点。 TiXmlElement*FirstPerson=RootElement->FirstChildElement(); 获得第一个Person的name节点和age节点和ID属性。 TiXmlElement*NameElement=FirstPerson->FirstChildElement(); TiXmlElement*AgeElement=NameElement->NextSiblingElement(); TiXmlAttribute*IDAttribute=FirstPerson->FirstAttribute(); 输出第一个Person的name内容,即周星星;age内容,即;ID属性,即。 cout<<NameElement->FirstChild()->Value()<<endl; cout<<AgeElement->FirstChild()->Value()<<endl; cout<<IDAttribute->Value()<<endl; } string&e) { true; } intmain() { stringfileName=info.xml"; CreateXmlFile(fileName); ReadXmlFile(fileName); } 1.首先下载TinyXML库的文件,这里给出链接,大家自己去下吧 2.在TinyXML的目录里面找到tinystr.h,tinyxml.h,tinystr.cpp,tinyxml.cpp,tinyxmlerror.cpp,tinyxmlparser.cpp六个文件加入到刚刚创建的项目中去 3.在相应的工程文件中加入两个头文件 4.tinystr.cpp,tinyxmlparser.cpp六个文件的第一行加入头文件
在TinyXML中,根据XML的各种元素来定义了一些类:
<?
xmlversion="1.0"standalone=no>
<!–Ourtodolistdata–> <ToDo> <Itempriority="1">Gotothe<bold>Toystore!</bold></Item> <Itempriority="2">Dobills</Item> </ToDo>
TiXmlElement
*
root
=
document.FirstChildElement(
"
Document
);
if (root) { TiXmlElement*element=root->FirstChildElement("Element); if(element) childChild(child) child2NextSiblingElement((child2) { Finallydosomethinguseful. TiXmlHandledocHandle(
&
document);
TiXmlElement child2 docHandle.FirstChild( ).FirstChild( Element ).Child( Child , 1 ).ToElement(); (child2) dosomethinguseful 一、读取XML,设置节点文本 如下XML片段: xmlversion="1.0"encoding="UTF-8"standalone="yes"
?>
< ZXML > ZAPP VBS_RUNTIME_PARAMS BROADCAST_VERSION info ="版本" 8 </ BROADCAST_VERSION Broadcast FileCount ="资源文件个数" 69 FileCount SOURCE_1 ID ="图片编号" ID Version ="图片版本" Version Path ="图片路径" /mnt/share/1.bmp Path FileMode ="文件处理模式" 0 FileMode SOURCE_2 /mnt/share/2.bmp 2 . > 要设置BROADCAST_VERSION节点的值 8为其他值,可参考如下代码(将值加1): 用ReplaceChild( TiXmlNode* replaceThis,const TiXmlNode& withThis )方法替换 TiXmlDocumentdoc("zapp.conf"); doc.LoadFile(); TiXmlHandledocHandle( doc); TiXmlElement Broadcast_ver ).FirstChildElement( ).ToElement(); TiXmlNode oldnode -> FirstChild(); const char ver GetText(); int oldVer atoi(ver); CStringnewVer; newVer.Format( %d + ); TiXmlTextnewText(newVer); Broadcast_ver ReplaceChild(oldnode,newText); AfxMessageBox(Broadcast_ver GetText()); // 输出值 doc.SaveFile(); 二,删除节点,属性值 RemoveChild( TiXmlNode* removeThis )方法删除父节点的子节点, RemoveAttribute( const char * name )方法删除属性值. 例如删除BROADCAST_VERSION节点 ).ToElement(); TiXmlNode node FirstChild( ); Broadcast_ver RemoveChild(node); 也可以删除整个SOURCE_1节点: ); Broadcast 删除BROADCAST_VERSION的info属性: ).ToElement(); Broadcast_ver RemoveAttribute( ); 删除info 可以借助NextSiblingElement()方法实现递归删除. 三,添加节点,51); font-family:Arial; font-size:14px; line-height:26px">例如在SOURCE_3下添加BROADCAST_PID节点: ).ToElement(); TiXmlElement Broadcast_Pid new TiXmlElement( BROADCAST_PID ); TiXmlText text TiXmlText( 7215 ); Broadcast_Pid SetAttribute( thepid LinkEndChild(text); Broadcast LinkEndChild(Broadcast_Pid); 将在SOURCE_3后添加新的节点: BROADCAST_PID ="thepid" 四,最后说一下中文乱码的问题 乱码是由于GB2312与UTF8之间转换不当造成的,tinyxml在处理UTF8本身没有问题,当你打开一个UTF8的文档,可以在加载的时候指定UTF8的方式,或者文档声明处指明的编码格式,tinyxml会按照相应的编码格式加载,但很多时候当我们输出或写入中文字段时会出现乱码,无论在内存,还是打印出来的内容.这是因为我们的软件通常是GB2312编码,而读取或写入的内容是UTF8,自然就会出错.可以借助网上的两个函数来实现转换(原作者不详): void ConvertUtf8ToGBK(CString strUtf8) intlenMultiByteToWideChar(CP_UTF8,0-1); unsignedshortwszGBKnewunsigned[len+]; memset(wszGBK,len2); MultiByteToWideChar(CP_UTF8,wszGBK,len); lenWideCharToMultiByte(CP_ACP,NULL); charszGBK]; memset(szGBK,0)">); WideCharToMultiByte(CP_ACP,szGBK,len,NULL); strUtf8szGBK; delete[]szGBK; delete[]wszGBK; } ConvertGBKToUtf8(CString strGBK) MultiByteToWideChar(CP_ACP,(LPCTSTR)strGBK,0)">wszUtf8]; memset(wszUtf8,0)">); MultiByteToWideChar(CP_ACP,wszUtf8,0)">WideCharToMultiByte(CP_UTF8,0)">szUtf8]; memset(szUtf8,0)">); WideCharToMultiByte(CP_UTF8,szUtf8,NULL); strGBKszUtf8; delete[]szUtf8; delete[]wszUtf8; } 现在越来越多的数据和配置采用了xml格式来存放和进行传输解析了。在c++方面,没有本地支持的库,所以需要我们自己去找一下。微软的msxml说实话,确实不咋地,尤其是com的类型变量名字一直指针,让众人看上去就比较反感。开源的tinyxml在这方便做的还不错。简单介绍下使用过程的一点小经验。 在这里发下牢骚,VC6.0以后的各个版本的VS环境对于C++的智能感知都是那么的SB,不管你怎么配置,怎么google都让你非常抓狂,就是不出来。算了不说了。 从网站上下载tinyxml,下载之后解压打开文件夹,里面有一些测试例子,tinyxml.sln支持vs2010了都,不管这些,怎么需要的是那个xml类库。 使用tinyxml我们只需要 tinyxml.cpp, tinyxml.h,51); font-family:Arial; font-size:14px; line-height:26px"> tinyxmlerror.cpp,51); font-family:Arial; font-size:14px; line-height:26px"> tinyxmlparser.cpp,51); font-family:Arial; font-size:14px; line-height:26px"> tinystr.cpp,153)">tinystr.h 6个文件即可。注意一旦少拷贝了其中tinyxmlerror.cpp,tinyxmlparser.cpp,其中一个或者两个,就会报告link错误,呵呵 在目标源文件的头部,添加 #include"tinyxml.h"和#include "tinystr.h" 我们使用xml文件,无外乎这几种操作, 1. 遍历整个xml返回一棵树select 2. 查找特定节点的属性/文本值select 3.插入特定位置一个节点insert 4.更新特定节点的属性/文本值 update 5.创建xml文件 create 6.who knows 据一位网友的博文里面提到,基本应该涵盖数据库的所有操作,xml操作应该像操作数据库一样。我觉得甚是有道理啊。 那么我来列举下,我搜集以及测试成功的相关的操作代码吧,希望能节省一些大家学习的时间。 1.create xml操作
2.遍历打印xml文件 select操作
copy
3.获取单个节点值 copy
copy
4.删除节点操作 copy
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |