游戏服务端之xml类型转换

本文介绍如何使用TinyXML进行不同类型数据的读取与转换,并提供了一个通用配置管理类的实现,帮助开发者更好地管理配置文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上一篇博文我已经说明了服务端添加tinyxml的基本操作及基本用法。
我的服务端之添加xml解释器 http://blog.youkuaiyun.com/yitouhan/article/details/17453159
但是可以看出tinyxml读出的数据是不做类型匹配的,也就是说tinyxml读出的数据都是字符串。但是在实际应用中,我还需要其它的数据类型,例如整型和浮点型。
实现类型转换的关键在istringstream,下面的链接有介绍

http://baike.baidu.com/link?url=t0pOzUA1bmDBQaHlCN4D7LjvF7ow9xryeCbcX5IP0SxsGfwEjPyZcIU37goGRTt-ccs3pKU1g4OrMdXgaN6Woq

    #ifndef COMMONCONFIG_H  
    #define COMMONCONFIG_H  
      
    #include <string>  
    #include <sstream>  
      
    // 将字符串转成基础数据类型,非基础类型需显示定义  
    template<class T>  
    bool StringToBaseType(const std::string& str, T& val)  
    {  
        std::istringstream stream;  
        stream.str(str);  
        if (stream>>val)  
        {  
            return true;  
        }  
        return false;  
    }  
      
    // 将基础数据类型转成字符串,非基础类型需显示定义  
    template<class T>  
    bool BaseTypeToString(const T& src, std::string& tar)  
    {  
        std::ostringstream stream;  
        if (stream<<src)  
        {  
            tar = stream.str();  
            return true;  
        }  
        return false;  
    }  
      
    #include "tinyxml/tinyxml.h"  
      
      
    template<class T>  
    static bool GetSubNodeValue(TiXmlElement *element, const std::string& name, T& val)  
    {  
        if (!element) return false;  
        TiXmlElement *TmpElement = element->FirstChildElement(name.c_str());  
        return GetNodeValue(TmpElement, val);  
    }  
    template<class T>  
    static bool SetSubNodeValue(TiXmlElement *element, const std::string& name, T& val)  
    {  
        if (!element) return false;  
        TiXmlElement *TmpElement = element->FirstChildElement(name.c_str());  
        return SetNodeValue(TmpElement, val);  
    }  
      
    // 读写如下节点element的值,不支持形如<element/>的空值  
    // <element>s_val</element>  
    template<class T>  
    static bool GetNodeValue(TiXmlElement *element, T& val)  
    {  
        if (!element || !element->FirstChild() || !StringToBaseType(element->GetText(), val))  
        {  
            return false;  
        }  
        return true;  
    }  
      
      
    class ConfigElementBase  
    {  
    public:  
        ConfigElementBase():m_element(0) {}  
        virtual ~ConfigElementBase() {}  
      
        void SetElement(TiXmlElement *element) { m_element = element; }  
      
        // 供子类列表中获取偏移地址  
        virtual ConfigElementBase* offset() = 0;  
        // 将子节点读到相应成员数据中  
        virtual bool read() = 0;  
        // 将成员数据写入文件  
        virtual bool write() = 0;  
      
    protected:  
        // 获取子节点的值,不适用有多个同名子节点的情况  
        template<class T>  
        bool GetValue(const char *name, T* value)  
        {  
            if (m_element == 0) return false;  
            return GetSubNodeValue(m_element, name, *value);  
        }  
        bool GetValue(const char *name, ConfigElementBase* value)  
        {  
            if (m_element == 0) return false;  
            value->SetElement(m_element->FirstChildElement(name));  
            return value->read();  
        }  
      
        // 获取子节点的值,适用有多个同名子节点的情况,与数组对应  
        template<class T>  
        bool GetListValue(const char *name, T* list_value, int& list_len, int list_max_len)  
        {  
            list_len = 0;  
            if (m_element == 0)  
            {  
                return false;  
            }  
            TiXmlElement *tmp_element = m_element->FirstChildElement(name);  
            for ( ;list_len < list_max_len && tmp_element != 0; ++list_len, ++list_value, tmp_element = tmp_element->NextSiblingElement(name))  
            {  
                if (!GetNodeValue(tmp_element, *list_value)) return false;  
            }  
            return true;  
        }  
        bool GetListValue(const char *name, ConfigElementBase* list_value, int& list_len, int list_max_len)  
        {  
            list_len = 0;  
            if (m_element == 0)  
            {  
                return false;  
            }  
            TiXmlElement *tmp_element = m_element->FirstChildElement(name);  
            for ( ;list_len < list_max_len && tmp_element != 0; ++list_len)  
            {  
                list_value->SetElement(tmp_element);  
                if (!list_value->read())return false;  
                list_value = list_value->offset();  
                tmp_element = tmp_element->NextSiblingElement(name);  
            }  
            return true;  
        }  
      
        // 设置子节点的值,不适用有多个同名子节点的情况  
        template<class T>  
        bool SetValue(const char *name, T* value)  
        {  
            if (m_element == 0) return false;  
      
            TiXmlElement * tmp_element = m_element->FirstChildElement(name);  
            if (!tmp_element)  
            {  
                TiXmlElement insert_node(name);  
                tmp_element = (TiXmlElement *)m_element->InsertEndChild(insert_node);  
            }  
            if (!tmp_element->FirstChild())  
            {  
                std::string tmp_value;  
                BaseTypeToString(*value, tmp_value);  
                TiXmlText sub_node(tmp_value);  
                tmp_element->InsertEndChild(sub_node);  
                return true;  
            }  
            return SetSubNodeValue(m_element, name, *value);  
        }  
        bool SetValue(const char *name, ConfigElementBase* value)  
        {  
            if (m_element == 0) return false;  
            TiXmlElement * tmp_element = m_element->FirstChildElement(name);  
            if (!tmp_element)  
            {  
                TiXmlElement insert_node(name);  
                m_element->InsertEndChild(insert_node);  
                tmp_element = m_element->FirstChildElement(name);  
            }  
            value->SetElement(tmp_element);  
            return value->write();  
        }  
      
        // 设置子节点的值,适用有多个同名子节点的情况,与数组对应  
        template<class T>  
        bool SetListValue(const char *name, T* list_value, int list_len)  
        {  
            if (m_element == 0 || list_len < 0)  
            {  
                return false;  
            }  
            TiXmlElement *tmp_element = m_element->FirstChildElement(name);  
            for(int i=0;i<list_len;++i,++list_value)  
            {  
                if (!tmp_element)  
                {  
                    TiXmlElement insert_node(name);  
                    tmp_element = (TiXmlElement *)m_element->InsertEndChild(insert_node);  
                }  
                if (!tmp_element->FirstChild())  
                {  
                    std::string tmp_value;  
                    BaseTypeToString(*list_value, tmp_value);  
                    TiXmlText sub_node(tmp_value);  
                    tmp_element->InsertEndChild(sub_node);  
                }  
                else  
                {  
                    if (!SetNodeValue(tmp_element, *list_value)) return false;  
                }  
                tmp_element = tmp_element->NextSiblingElement(name);  
            }  
            while(tmp_element)  
            {  
                TiXmlElement *to_remove = tmp_element;  
                tmp_element = tmp_element->NextSiblingElement(name);  
                m_element->RemoveChild(to_remove);  
            };  
            return true;  
        }  
        bool SetListValue(const char *name, ConfigElementBase* list_value, int list_len)  
        {  
            if (m_element == 0 || list_len < 0)  
            {  
                return false;  
            }  
            TiXmlElement *tmp_element = m_element->FirstChildElement(name);  
            for(int i=0;i<list_len;++i)  
            {  
                if (!tmp_element)  
                {  
                    TiXmlElement insert_node(name);  
                    tmp_element = (TiXmlElement *)m_element->InsertEndChild(insert_node);  
                }  
      
                list_value->SetElement(tmp_element);  
                if (!list_value->write()) return false;  
      
                list_value= list_value->offset();  
                tmp_element = tmp_element->NextSiblingElement(name);  
            }  
            while(tmp_element)  
            {  
                TiXmlElement *to_remove = tmp_element;  
                tmp_element = tmp_element->NextSiblingElement(name);  
                m_element->RemoveChild(to_remove);  
            };  
            return true;  
        }  
      
      
        // 至少有一个节点的xml结构  
        TiXmlElement *m_element;  
      
    private:  
    };  
      
    #endif  


下面是测试用例



    <?xml version="1.0" encoding="utf-8"?>  
    <blog>    
        <blogger>一头汗</blogger>  
        <date>20131221</date>  
        <temperature>10.1</temperature>  
    </blog>   

    #include <stdio.h>  
    #include <time.h>  
      
    #include "globalvariable.h"  
    #include "luaengine.h"  
    #include "gamesocket.h"  
    #include "log.h"  
    #include "dll.h"  
    #include "MyDll.h"  
    #include "gametime.h"  
    #include "frame.h"  
    #include "datatable.h"  
    #include "showcrash.h"  
    #include "globalfunction.h"  
    #include "commonconfig.h"  
      
    void Init()  
    {  
      
        TiXmlDocument doc;  
      
        if (doc.LoadFile("conf/info.xml"))  
        {  
            TiXmlElement* rootElement = doc.RootElement();  
            if (rootElement == NULL)  
            {  
                return ;  
            }  
            char blogger[16]={0};  
            GetSubNodeValue(rootElement, "blogger",blogger);  
            printf("博主:%s\n", blogger);  
            int date = 0;  
            GetSubNodeValue(rootElement, "date",date);  
            printf("日期:%d\n", date);  
            float temperature = 0.0;  
            GetSubNodeValue(rootElement,  "temperature", temperature);  
            printf("温度:%f\n", temperature);  
        }  
    }  
      
      
    int main()  
    {  
        Init();  
      
        return 0;  
    }  

输出结果:


原文地址:http://blog.youkuaiyun.com/yitouhan/article/details/17333191

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值