微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

XML与C++对象的相互转化

介绍

这个例子假设你在用一个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;
}
};
&nbsp;
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:%s\n",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:%s\n",

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&apos;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:\dev\tinyxml> Debug\tinyxml_1.exe example1.xml example1.xml: Document + Declaration + Element [Hello] (No attributes) + Text: [World]

原文地址:https://www.jb51.cc/xml/300636.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。