现在的位置: 首页 > 综合 > 正文

TinyXML中文指南三

2014年01月16日 ⁄ 综合 ⁄ 共 6698字 ⁄ 字号 评论关闭

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

介绍

这个例子假设你在用一个XML文件来加载和保存你的应用程序配置,举例来说,有点像example4.xml。

有许多方法可以做到这点。例如,看看TinyBind项目:http://sourceforge.net/projects/tinybind

这一节展示了一种普通老式的方法来使用XML加载和保存一个基本的对象结构。

建立你的对象类

从一些像这样的基本类开始:

#include
<string
>
#include
<map>
using
namespace
std
;

typedef
std
::map<std
::string
,std
::string
> MessageMap;

// 基本的窗口抽象 - 仅仅是个示例

class
WindowSettings
{
    public
:
    int
x,y,w,h;
    string
name;
    
     WindowSettings()
         : x(0), y(0), w(100), h(100), name("Untitled"
)
     {
     }
    
     WindowSettings(int
x, int
y, int
w, int
h, const string
& name)
     {
        this
->x=x;
        this
->y=y;
        this
->w=w;
        this
->h=h;
        this
->name=name;
     }
};
&nbsp;
class
ConnectionSettings
{
    public
:
    string
ip
;
    double
timeout;
};

class
AppSettings
{
    public
:
    string
m_name;
     MessageMap m_messages;
    list
<WindowSettings> m_windows;
     ConnectionSettings m_connection;
    
     AppSettings() {}
    
    void
save(const char
* pFilename);
    void
load(const char
* pFilename);
    
    // 仅用于显示它是如何工作的

    void
setDemoValues()
     {
         m_name="MyApp"
;
         m_messages.clear();
         m_messages["Welcome"
]="Welcome to "
+m_name;
         m_messages["Farewell"
]="Thank you for using "
+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对象树,怎样保存并再次加载:

int
main(void
)
{
     AppSettings settings;
    
     settings.save("appsettings2.xml"
);
     settings.load("appsettings2.xml"
);
    return
0;
}

接下来的main()展示了如何创建,修改,保存和加载一个settings结构:

int
main(void
)
{
    // 区块:定制并保存settings

     {
         AppSettings settings;
         settings.m_name="HitchHikerApp"
;
         settings.m_messages["Welcome"
]="Don’t Panic"
;
         settings.m_messages["Farewell"
]="Thanks for all the fish"
;
         settings.m_windows.push_back(WindowSettings(15,25,300,250,"BookFrame"
));
         settings.m_connection.ip="192.168.0.77"
;
         settings.m_connection.timeout=42.0;
        
         settings.save("appsettings2.xml"
);
     }
    
    // 区块:加载settings

     {
         AppSettings settings;
         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: Show window ’%s’ at %d,%d (%d x %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_name.c_str(),

                            settings.m_messages["Farewell"
].c_str());
     }
    return
0;
}

当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

有很多方法能够做到把文档对象保存到文件中,这就是其中一个:

void
AppSettings::save(const char
* pFilename)
{
     TiXmlDocument doc;
     TiXmlElement* msg;
     TiXmlComment * comment;
    string
s;
     TiXmlDeclaration* decl = new
TiXmlDeclaration( "1.0"
, ""
, ""
);
     doc.LinkEndChild( decl );
    
     TiXmlElement * root = new
TiXmlElement(m_name.c_str());
     doc.LinkEndChild( root );
    
     comment = new
TiXmlComment();
     s=" Settings for "
+m_name+" "
;
     comment->SetValue(s.c_str());
     root->LinkEndChild( comment );
    
    // 区块:messages

     {
         MessageMap::iterator iter;
        
         TiXmlElement * msgs = new
TiXmlElement( "Messages"
);
         root->LinkEndChild( msgs );
        
        for
(iter=m_messages.begin(); iter != m_messages.end(); iter++)
         {
             const string
& key=(*iter).first;
             const string
& value=(*iter).second;
             msg = new
TiXmlElement(key.c_str());
             msg->LinkEndChild( new
TiXmlText(value.c_str()));
             msgs->LinkEndChild( msg );
         }
     }
    
    // 区块:windows

     {
         TiXmlElement * windowsNode = new
TiXmlElement( "Windows"
);
         root->LinkEndChild( windowsNode );
        
        list
<WindowSettings>::iterator iter;
        
        for
(iter=m_windows.begin(); iter != m_windows.end(); iter++)
         {
             const WindowSettings& w=*iter;
            
             TiXmlElement * window;
             window = new
TiXmlElement( "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 = new
TiXmlElement( "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。

void
AppSettings::load(const char
* pFilename)
{
     TiXmlDocument doc(pFilename);
    if
(!doc.LoadFile()) return
;
    
     TiXmlHandle hDoc(&doc);
     TiXmlElement* pElem;
     TiXmlHandle hRoot(0);
    
    // 区块:name

     {
         pElem=hDoc.FirstChildElement().Element();
        // 必须有一个合法的根结点,如果没有则温文地处理(译注:直接返回


        if
(!pElem) return
;
         m_name=pElem->Value();
        
        // 保存起来以备后面之用

         hRoot=TiXmlHandle(pElem);
     }
    
    // 区块:string table

     {
         m_messages.clear(); // 清空已有的table

        
         pElem=hRoot.FirstChild( "Messages"
).FirstChild().Element();
        for
( pElem; pElem; pElem=pElem->NextSiblingElement())
         {
             const char
*pKey=pElem->Value();
             const char
*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())
         {
             WindowSettings w;
             const char
*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);
         }
     }
}

抱歉!评论已关闭.