游戏服务端之xml类型转换

上一篇博文我已经说明了服务端添加tinyxml的基本操作及基本用法。
我的服务端之添加xml解释器 http://blog.csdn.net/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;
}
输出结果:


猜你喜欢

转载自blog.csdn.net/a374826954/article/details/17333191