介绍
这个例子假设你在用一个XML文件来加载和保存你的应用程序配置,举例来说,有点像example4.xml。
有许多方法可以做到这点。例如,看看TinyBind项目:http://sourceforge.net/projects/tinybind
这一节展示了一种普通老式的方法来使用XML加载和保存一个基本的对象结构。
建立你的对象类
从一些像这样的基本类开始:
#include<string> #include<map> usingnamespacestd; typedefstd::map<std::string,std::string>MessageMap; //基本的窗口抽象-仅仅是个示例 classWindowSettings { public: intx,y,w,h; stringname; WindowSettings() :x(0),y(0),w(100),h(100),name("Untitled") { } WindowSettings(intx,inty,intw,inth,conststring&name) { this->x=x; this->y=y; this->w=w; this->h=h; this->name=name; } }; classConnectionSettings { public: stringip; doubletimeout; }; classAppSettings { public: stringm_name; MessageMapm_messages; list<WindowSettings>m_windows; ConnectionSettingsm_connection; AppSettings(){} voidsave(constchar*pFilename); voidload(constchar*pFilename); //仅用于显示它是如何工作的 voidsetDemoValues() { m_name="MyApp"; m_messages.clear(); m_messages["Welcome"]="Welcometo"+m_name; m_messages["Farewell"]="Thankyouforusing"+m_name; m_windows.clear(); m_windows.push_back(WindowSettings(15,15,400,250,"Main")); m_connection.ip="Unknown"; m_connection.timeout=123.456; } };
这是一个基本的mian(),它向我们展示了怎样创建一个默认的settings对象树,怎样保存并再次加载:
intmain(void) { AppSettingssettings; settings.save("appsettings2.xml"); settings.load("appsettings2.xml"); return0; }
接下来的main()展示了如何创建,修改,保存和加载一个settings结构:
intmain(void) { //区块:定制并保存settings { AppSettingssettings; settings.m_name="HitchHikerApp"; settings.m_messages["Welcome"]="Don’tPanic"; settings.m_messages["Farewell"]="Thanksforallthefish"; settings.m_windows.push_back(WindowSettings(15,25,300,"BookFrame")); settings.m_connection.ip="192.168.0.77"; settings.m_connection.timeout=42.0; settings.save("appsettings2.xml"); } //区块:加载settings { AppSettingssettings; settings.load("appsettings2.xml"); printf("%s:%sn",settings.m_name.c_str(), settings.m_messages["Welcome"].c_str()); WindowSettings&w=settings.m_windows.front(); printf("%s:Showwindow’%s’at%d,%d(%dx%d)n", settings.m_name.c_str(),w.name.c_str(),w.x,w.y,w.w,w.h); printf("%s:%sn", settings.m_messages["Farewell"].c_str()); } return0; }
当save()和load()完成后(请看下面),运行这个main()就会在控制台看到:
HitchHikerApp: Don’t Panic HitchHikerApp: Show window ‘BookFrame’ at 15,25 (300 x 100) HitchHikerApp: Thanks for all the fish
把C++状态编码成XML
有很多方法能够做到把文档对象保存到文件中,这就是其中一个:
voidAppSettings::save(constchar*pFilename) { TiXmlDocumentdoc; TiXmlElement*msg; TiXmlComment*comment; strings; TiXmlDeclaration*decl=newTiXmlDeclaration("1.0","",""); doc.LinkEndChild(decl); TiXmlElement*root=newTiXmlElement(m_name.c_str()); doc.LinkEndChild(root); comment=newTiXmlComment(); s="Settingsfor"+m_name+""; comment->SetValue(s.c_str()); root->LinkEndChild(comment); //区块:messages { MessageMap::iteratoriter; TiXmlElement*msgs=newTiXmlElement("Messages"); root->LinkEndChild(msgs); for(iter=m_messages.begin();iter!=m_messages.end();iter++) { conststring&key=(*iter).first; conststring&value=(*iter).second; msg=newTiXmlElement(key.c_str()); msg->LinkEndChild(newTiXmlText(value.c_str())); msgs->LinkEndChild(msg); } } //区块:windows { TiXmlElement*windowsNode=newTiXmlElement("Windows"); root->LinkEndChild(windowsNode); list<WindowSettings>::iteratoriter; for(iter=m_windows.begin();iter!=m_windows.end();iter++) { constWindowSettings&w=*iter; TiXmlElement*window; window=newTiXmlElement("Window"); windowsNode->LinkEndChild(window); window->SetAttribute("name",w.name.c_str()); window->SetAttribute("x",w.x); window->SetAttribute("y",w.y); window->SetAttribute("w",w.w); window->SetAttribute("h",w.h); } } //区块:connection { TiXmlElement*cxn=newTiXmlElement("Connection"); root->LinkEndChild(cxn); cxn->SetAttribute("ip",m_connection.ip.c_str()); cxn->SetDoubleAttribute("timeout",m_connection.timeout); } doc.SaveFile(pFilename); }
用修改过的main运行会生成这个文件:
<?xml version="1.0" ?> <HitchHikerApp> <!– Settings for HitchHikerApp –> <Messages> <Farewell>Thanks for all the fish</Farewell> <Welcome>Don't Panic</Welcome> </Messages> <Windows> <Window name="BookFrame" x="15" y="25" w="300" h="250" /> </Windows> <Connection ip="192.168.0.77" timeout="42.000000" /> </HitchHikerApp>
从XML中解码出状态
就像编码一样,也有许多方法可以让你从自己的C++对象结构中解码出XML。下面的方法使用了TiXmlHandles。
voidAppSettings::load(constchar*pFilename) { TiXmlDocumentdoc(pFilename); if(!doc.LoadFile())return; TiXmlHandlehDoc(&doc); TiXmlElement*pElem; TiXmlHandlehRoot(0); //区块:name { pElem=hDoc.FirstChildElement().Element(); //必须有一个合法的根结点,如果没有则温文地处理(译注:直接返回) if(!pElem)return; m_name=pElem->Value(); //保存起来以备后面之用 hRoot=TiXmlHandle(pElem); } //区块:stringtable { m_messages.clear();//清空已有的table pElem=hRoot.FirstChild("Messages").FirstChild().Element(); for(pElem;pElem;pElem=pElem->NextSiblingElement()) { constchar*pKey=pElem->Value(); constchar*pText=pElem->GetText(); if(pKey&&pText) { m_messages[pKey]=pText; } } } //区块:windows { m_windows.clear();//清空链表 TiXmlElement*pWindowNode=hRoot.FirstChild("Windows") .FirstChild().Element(); for(pWindowNode;pWindowNode; pWindowNode=pWindowNode->NextSiblingElement()) { WindowSettingsw; constchar*pName=pWindowNode->Attribute("name"); if(pName)w.name=pName; pWindowNode->QueryIntAttribute("x",&w.x);//如果失败,原值保持现状 pWindowNode->QueryIntAttribute("y",&w.y); pWindowNode->QueryIntAttribute("w",&w.w); pWindowNode->QueryIntAttribute("hh",&w.h); m_windows.push_back(w); } } //区块:connection { pElem=hRoot.FirstChild("Connection").Element(); if(pElem) { m_connection.ip=pElem->Attribute("ip"); pElem->QueryDoubleAttribute("timeout",&m_connection.timeout); } } }
dump_to_stdout的完整列表
下面是一个可直接运行的示例程序,使用上面提到过的递归遍历方式,可用来加载任意的XML文件并把结构输出到STDOUT上。
//指南示例程序 #include"stdafx.h" #include"tinyxml.h" //———————————————————————- //STDOUT输出和缩进实用函数 //———————————————————————- constunsignedintNUM_INDENTS_PER_SPACE=2; constchar*getIndent(unsignedintnumIndents) { staticconstchar*pINDENT="+"; staticconstunsignedintLENGTH=strlen(pINDENT); unsignedintn=numIndents*NUM_INDENTS_PER_SPACE; if(n>LENGTH)n=LENGTH; return&pINDENT[LENGTH-n]; } //与getIndent相同,但最后没有“+” constchar*getIndentAlt(unsignedintnumIndents) { staticconstchar*pINDENT=""; staticconstunsignedintLENGTH=strlen(pINDENT); unsignedintn=numIndents*NUM_INDENTS_PER_SPACE; if(n>LENGTH)n=LENGTH; return&pINDENT[LENGTH-n]; } intdump_attribs_to_stdout(TiXmlElement*pElement,unsignedintindent) { if(!pElement)return0; TiXmlAttribute*pAttrib=pElement->FirstAttribute(); inti=0; intival; doubledval; constchar*pIndent=getIndent(indent); printf("n"); while(pAttrib) { printf("%s%s:value=[%s]",pIndent,pAttrib->Name(),pAttrib->Value()); if(pAttrib->QueryIntValue(&ival)==TIXML_SUCCESS)printf("int=%d",ival); if(pAttrib->QueryDoubleValue(&dval)==TIXML_SUCCESS)printf("d=%1.1f",dval); printf("n"); i++; pAttrib=pAttrib->Next(); } returni; } voiddump_to_stdout(TiXmlNode*pParent,unsignedintindent=0) { if(!pParent)return; TiXmlNode*pChild; TiXmlText*pText; intt=pParent->Type(); printf("%s",getIndent(indent)); intnum; switch(t) { caseTiXmlNode::DOCUMENT: printf("Document"); break; caseTiXmlNode::ELEMENT: printf("Element[%s]",pParent->Value()); num=dump_attribs_to_stdout(pParent->ToElement(),indent+1); switch(num) { case0:printf("(Noattributes)");break; case1:printf("%s1attribute",getIndentAlt(indent));break; default:printf("%s%dattributes",getIndentAlt(indent),num);break; } break; caseTiXmlNode::COMMENT: printf("Comment:[%s]",pParent->Value()); break; caseTiXmlNode::UNKNOWN: printf("Unknown"); break; caseTiXmlNode::TEXT: pText=pParent->ToText(); printf("Text:[%s]",pText->Value()); break; caseTiXmlNode::DECLARATION: printf("Declaration"); break; default: break; } printf("n"); for(pChild=pParent->FirstChild();pChild!=0;pChild=pChild->NextSibling()) { dump_to_stdout(pChild,indent+1); } } //加载指定的文件并把它的结构输出到STDOUT上 voiddump_to_stdout(constchar*pFilename) { TiXmlDocumentdoc(pFilename); boolloadOkay=doc.LoadFile(); if(loadOkay) { printf("n%s:n",pFilename); dump_to_stdout(&doc); } else { printf("Failedtoloadfile"%s”n",pFilename); } } //———————————————————————- //main(),打印出从命令行指定的文件 //———————————————————————- intmain(intargc,char*argv[]) { for(inti=1;i<argc;i++) { dump_to_stdout(argv[i]); } return0; }
从命令行或者DOS窗口运行它,例如:
C:devtinyxml> Debugtinyxml_1.exe example1.xml example1.xml: Document + Declaration + Element [Hello] (No attributes) + Text: [World] (编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|