(原)C++解析XML生成类对象_v1.0 函数指针
要写一个xml解析,解析后获得到的数据变成各个类的对象.
解析有现成的库,使用tinyxml,但是解析出来的类库如何变成各个类的对象,
例如一下这个xml,
<musics>
<music id="1">
<name>黑色幽默</name>
<albumName>Jay</albumName>
<year>2000</year>
</music>
<music id="2">
<name>爱在西元前</name>
<albumName>范特西</albumName>
<year>2001</year>
</music>
<music id="3">
<name>回到过去</name>
<albumName>八度空间</albumName>
<year>2002</year>
</music>
<music id="4">
<name>东风破</name>
<albumName>叶惠美</albumName>
<year>2003</year>
</music>
<music id="5">
<name>七里香</name>
<albumName>七里香</albumName>
<year>2004</year>
</music>
<music id="6">
<name>一路向北</name>
<albumName>十一月的萧邦</albumName>
<year>2005</year>
</music>
</musics>
我们可以设计一个CMusics类,里头包含CMusic数组
class CMusic
{
public:
CMusic();
virtual ~CMusic(); private:
string m_name;
string m_albumName;
int m_year;
};
class CMusic
class CMusics
{
public:
CMusics();
virtual ~CMusics();
vector<CMusic*> m_musics; };
最初的想法在CMusic中定义一个函数
class CMusic
{
public:
CMusic();
virtual ~CMusic();
//第一版
void SetValue( string key, void* value )
{
if ( key == "name" )
{
this->m_name = (char*)value;
}
else if( key == "albumName" )
{
this->m_albumName = (char*)value;
}
else if ( key == "year" )
{
this->m_year = (int)value;
}
//比较纠结...如果有多个对象,那不是要比多次...
} private:
string m_name;
string m_albumName;
int m_year;
};
改进版本
class CMusic
{
public:
CMusic()
{
m_mapfunc["id"] = &CMusic::SetName;
m_mapfunc["albumName"] = &CMusic::SetAlbumName;
m_mapfunc["year"] = &CMusic::SetYear;
}
virtual ~CMusic(); //改进版
typedef void ( CMusic::*Func )( string key, string strAttribute, void* value );
typedef map<string, Func>MusicMap; void SetName( string key, string strAttribute, void* value )
{
this->m_name = (char*)value;
} void SetAlbumName( string key, string strAttribute, void* value )
{
this->m_albumName = (char*)value;
} void SetYear( string key, string strAttribute, void* value )
{
this->m_year = *(int*)value;
} MusicMap m_mapfunc; private:
string m_name;
string m_albumName;
int m_year;
};
接着我们要定义一个处理xml的类IXmlAtom
class IXmlAtom
{
public:
/** 处理xml结点 */
virtual void DealXmlNode( string strNode, string strNodeAttribute, string Value) = ; //创建字节点指针
virtual IXmlAtom* CreateItem( string key ){ return NULL; } virtual void LoadXml(char* xmlPath); virtual void ParseXml(char* strXmlStream); private:
string DumpNode(TiXmlNode * pParent,TiXmlNode * pNode,IXmlAtom* pIAtom, int flag);
};
把需要生成xml对象的类继承该类.
DealXmlNode的作用是用来各个子类调用上面的回调函数
CreateItem的作用是当xml中嵌套多层xml的时候.根据名字创建类(如果只有一层xml数据则不需要重载这个函数)
其中DumpNode实现的代码如下:
string IXmlAtom::DumpNode(TiXmlNode * pParent,TiXmlNode * pNode,IXmlAtom* pIAtom, int flag)
{
if(pNode == NULL)
{
return "";
}
TiXmlText * pText = NULL;
TiXmlNode * pChildNode = NULL;
int t = pNode->Type();
if( t == TiXmlText::TINYXML_TEXT ) //节点类型是text节点
{
const char* pParentValue = pParent->Value();
pText = pNode->ToText();
string text = pText->Value();
pIAtom->DealXmlNode(pParentValue,"",text.c_str());
}
else if( t == TiXmlText::TINYXML_ELEMENT ) //节点类型是Element
{
int num = flag; const char* pNodeValue = pNode->Value(); //输出属性
TiXmlElement * pElement = pNode->ToElement();
TiXmlAttribute * pAttr = pElement->FirstAttribute();
if(pAttr != NULL)
{
string tmpAttrVal = "";
string tmpAttrName = "";
do
{
tmpAttrVal = pAttr->Value();
tmpAttrName = pAttr->Name();
pIAtom->DealXmlNode(pNodeValue,tmpAttrName,tmpAttrVal );
}while(pAttr = pAttr->Next());
}
}
//循环访问它的每一个元素
TiXmlNode * pTempParent = pNode;
for(pChildNode=pNode->FirstChild();pChildNode!=;pChildNode = pChildNode->NextSibling())
{
const char* data=pChildNode->Value();
IXmlAtom* pXmlAtom = pIAtom->CreateItem(pChildNode->Value());
DumpNode(pTempParent,pChildNode, pXmlAtom == NULL? pIAtom : pXmlAtom,flag+); }
return "";
}
调用
int main(int argc, char* argv[])
{
//printf("Hello World!\n");
CMusics music;
music.LoadXml("C:\\1.xml");
return ;
}
demo下载地址:
xml中包含多个对象的时候.写回调函数就每次都需要定义,可以使用c++函数模板来处理
(原)C++解析XML生成类对象_v1.0 函数指针的更多相关文章
- 动态加载Dll时,通过Type生成类对象
原文:动态加载Dll时,通过Type生成类对象 转:http://www.cnblogs.com/zfanlong1314/p/4197383.html "反射"其实就是利用程序集 ...
- 基类中定义的虚函数在派生类中重新定义时,其函数原型,包括返回类型、函数名、参数个数、参数类型及参数的先后顺序,都必须与基类中的原型完全相同 but------> 可以返回派生类对象的引用或指针
您查询的关键词是:c++primer习题15.25 以下是该网页在北京时间 2016年07月15日 02:57:08 的快照: 如果打开速度慢,可以尝试快速版:如果想更新或删除快照,可以投诉快照. ...
- 由剑指offer引发的思考——对象中虚函数指针的大小
先看一个简单的问题: 一.定义一个空的类型,对于其对象我们sizeof其大小,是1字节.因为我们定义一个类型,编译器必须为其分配空间,具体分配多少是编译器决定,vs是1字节,分配在栈区. 那,这一个字 ...
- Dom4J 解析xml ,类查询
/** * 从XML文件比对,传入provinceId 返回 provinceShortName * @param provinceid * @return */ public static Stri ...
- jaxb解析xml工具类
[quote]jaxb jdk 自带的解析xml的一种方式支持,只需要用注解对javabean进行数据绑定[/quote] package com.nnk.flowrecharge.common;im ...
- 使用dom4j解析xml为json对象
import java.util.List; import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.dom4j. ...
- java定义类 对象,引用,指针
java是根据面向对象编程,因此有类和对象的概念,类分为普通类与抽象类. 一.定义类 类由N个 构造器 成员变量 方法组成,可以不定义,也可以根据语法定义N个. [修饰符] class 类名{ 构 ...
- error LNK2019 无法解析的外部符号------类模板和内敛函数
今天用类模型实现一个单链表,开始是.h和.cpp将类模板的声明与实现分开写的,结果总是报错: 错误 error LNK2019: 无法解析的外部符号 ?$SingleList@H@@QAE@XZ),该 ...
- c++特性:指向类成员的指针和非类型类模板参数和函数指针返回值 参数推导机制和关联型别
一.c++允许定义指向类成员的指针,包括类函数成员指针和类数据成员指针 格式如下: class A { public: void func(){printf("This is a funct ...
随机推荐
- 网站资料收集 主要查看js的学习部分
1.Asp.Net MVC3.0基本的简单的可能都会用,更深入的使用还需加深研究,之后希望对MVC4.0和5.0进行对比学习,暂时看到@葡萄城控件技术团队博客的MVC5系列正在继续http://www ...
- 【转】Bluetooth数据包捕获
原文网址:http://www.cnblogs.com/hzl6255/p/3887013.html 这里介绍一种在Android上捕获蓝牙数据包的方法 1. 前提 首先你要有一部Android手机 ...
- Spring Bean之间的关系
bean之间的关系:继承和依赖继承bean的配置 Spring允许继承bean的配置,被继承的bean称为父bean,继承这个父bean的bean称为子bean 子bean从父bean中继承配置,包括 ...
- JS分页 + 获取MVC地址栏URL路径的最后参数
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport&quo ...
- golang资料整理 (整理 中...)
网站guide 官方文档 国内镜像 安装go 之后,用godoc 来安装自己本地的文档服务器, godoc -http=:8080 打开浏览器 输入localhost:8080 就可以看到文档说明了. ...
- HDU 1163 Eddy's digital Roots
Eddy's digital Roots Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Oth ...
- c#保存datagridview中的数据时报错 “动态SQL生成失败。找不到关键信息”
ilovejinglei 原文 C#中保存datagridview中的数据时报错"动态SQL生成失败.找不到关键信息" 问题描述 相关代码 using System; us ...
- 《Python基础教程(第二版)》学习笔记 -> 第三章 使用字符串
本章讲话介绍如何使用字符串格式化其他的值,并简单了解一下利用字符串的分割.联接.搜索等方法能做些什么. 基本字符串操作 所有标准的序列操作(索引.分片.乘法.判断成员资格.求长度.取最大最小值)对字符 ...
- LeetCode题解——Longest Palindromic Substring
题目: 给定一个字符串S,返回S中最长的回文子串.S最长为1000,且最长回文子串是唯一. 解法: ①遍历,对于每个字符,计算以它为中心的回文子串长度(长度为奇数),同时计算以它和右边相邻字符为中心的 ...
- bzoj 1034 [ZJOI2008]泡泡堂BNB(贪心)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1034 [题意] 给两个序列以任意顺序比较,求出最大和最小得分. [思路] 排序后使用贪 ...