• (原)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) = 0;
    
        //创建字节点指针
        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!=0;pChildNode = pChildNode->NextSibling())
        {
            const char* data=pChildNode->Value();
            IXmlAtom* pXmlAtom = pIAtom->CreateItem(pChildNode->Value());
            DumpNode(pTempParent,pChildNode, pXmlAtom == NULL? pIAtom : pXmlAtom,flag+1);
            
        }
        return "";
    }

    调用

    int main(int argc, char* argv[])
    {
        //printf("Hello World!
    ");
        CMusics music;
        music.LoadXml("C:\1.xml");
        return 0;
    }

    demo下载地址:

    ParseXml_V1.rar

    xml中包含多个对象的时候.写回调函数就每次都需要定义,可以使用c++函数模板来处理

  • 相关阅读:
    2014上半年-学习目录
    c++中智能输出文件
    如何在微博侧栏中加入自己的微博[js]
    oracle数据库性能
    Arcgis for Android 空间数据WKT与JSON描述
    echart 折线图、柱状图、饼图、环形图颜色修改
    Echarts横坐标倾斜,顶部显示数字
    解决svn中“工作副本已经锁定”,或者svn清理失败的解决方法
    Oracle 空间查询, 数据类型为 sdo_geometry
    OSS上无法使用字体文件解决方案
  • 原文地址:https://www.cnblogs.com/fjchenqian/p/3301104.html
Copyright © 2020-2023  润新知