tinyxml2的使用

       学习使用tinyxml2,参考https://www.cnblogs.com/happykoukou/p/6307257.html,以及官方tinyxml2的test。

       主要知识:

XMLDocument doc;//创建一个dom对象
doc.LoadFile();
doc.Parse(); //将字符串转为dom对象
auto key = doc.NewElement(const char* keyName);//创建一个key
doc.NewText(const char*);//创建一个value
InsertEndChild(key)
FirstChildElement(const char*);
GetText();
SetText(const char*);
NextSiblingElement();//兄弟节点

country.hpp

#pragma once

//删除指针
#define SAFE_DELETE(pRet) if(pRet != NULL) {delete pRet;pRet = NULL;}
//检查xml中的键是否存在,xml的结构已知,若不存在,直接退出
#define KEY_IS_NULL(key) if(key == nullptr){printf("%s is not found\n",#key);exit(-1);}

//为了简单化,以下几个类全部成员函数为public
class Province;
class City;

class City
{
public:
    std::string name;
    City(const std::string &name):name(name){}
};

class Province
{
public:
    std::string name;
    std::vector<City> vCities;
    Province(const std::string &name):name(name){}
    Province(){}
};

class Country
{
public:
    std::string name;
    std::vector<Province> vProvinces;

public:
    Country(const std::string &name):name(name){}
    Country(){}
    
    /**
     *  将本类的成员变量序列化到一个固定格式的xml文件中
     *  采用模板,可以不需要写 tinyxml2的头文件
     */
    template<typename T>
    int parseXML(T &doc, const std::string &fileName)
    {
        //xml头
        //R"(string)", string可以以原来的形式存在,“” 不需要转义符
        const char *declaration = R"(<?xml version="1.0" encoding="UTF-8"?>)";
        
        //将字符串解析到dom对象中
        doc.Parse(declaration);

        //new 一个 key
        //序列化std::string name;
        auto roof = doc.NewElement("country");
        auto keyCountryName = doc.NewElement("name");
        
        //插入value
        keyCountryName->InsertEndChild(doc.NewText(name.c_str()));
        
        //插入</>
        roof->InsertEndChild(keyCountryName);
        doc.InsertEndChild(roof);

        //序列化std::vector<Province> vProvinces;
        for(auto province : vProvinces)
        {
            auto keyProvince = doc.NewElement("province");
            roof->InsertEndChild(keyProvince);
            auto keyProvinceName = doc.NewElement("name");
            keyProvinceName->InsertEndChild(doc.NewText(province.name.c_str()));
            keyProvince->InsertEndChild(keyProvinceName);
            
            auto keyCities = doc.NewElement("cities");
            keyProvince->InsertEndChild(keyCities);

            //序列化std::vector<City> vCities;
            for(auto city : province.vCities)
            {
                auto keyCity = doc.NewElement("city");
                keyCity->InsertEndChild(doc.NewText(city.name.c_str()));
                keyCities->InsertEndChild(keyCity);
            }
        }
        //保存为xml文件
        return doc.SaveFile(fileName.c_str());
    }

    //反序列化xml文件成一个对象
    template<typename T>
    int convertXMLToObject(T &doc, const std::string &fileName)
    {
        int ret = doc.LoadFile(fileName.c_str());
        if(ret)
        {
            return ret;
        }

        //查找key,如果不存在,则退出程序。
        auto keyCountry  = doc.FirstChildElement("country");
        KEY_IS_NULL(keyCountry);
        auto keyCountryName = keyCountry->FirstChildElement("name");
        KEY_IS_NULL(keyCountryName);
        auto countryName = keyCountryName->GetText();
        if(countryName == nullptr)
        {
            return -1;
        }
        this->name = countryName;
        auto keyProvince = keyCountry->FirstChildElement("province");

        //反序列化std::vector<Province> vProvinces;
        while(keyProvince != nullptr)
        {            
            auto keyProvinceName = keyProvince->FirstChildElement("name");
            KEY_IS_NULL(keyProvinceName);

            auto provinceName = keyProvinceName->GetText();
            if(provinceName != nullptr)
            {
                Province province(provinceName);
                auto keyCities = keyProvince->FirstChildElement("cities");
                KEY_IS_NULL(keyCities);
                auto keyCity = keyCities->FirstChildElement("city");
                KEY_IS_NULL(keyCity);

                //反序列化std::vector<City> vCities;
                while(keyCity != nullptr)
                {
                    auto cityName = keyCity->GetText();
                    if(cityName != nullptr)
                    {
                        City city(cityName);
                        province.vCities.push_back(city);
                    }

                    //继续查找兄弟节点
                    keyCity = keyCity->NextSiblingElement(); 
                }
                this->vProvinces.push_back(province);
            }

            //继续查找兄弟节点
            keyProvince = keyProvince->NextSiblingElement();
        }

        return 0; 
    }

    //序列化对象到string
    std::string toString()
    {
        std::string s; 
        if(!name.empty())
        {
            s+= "country name: ";
            s+= name;
        }
        if(!vProvinces.empty())
        {
            for(auto province : vProvinces)
            {
                s+= " province name :";
                s+= province.name;
                if(!province.vCities.empty())
                {
                    s+= " city name: ";
                    for(auto city : province.vCities)
                    {
                        s+= city.name;
                        s+= " ";
                    }
                }
            }
        }
        return s;
    }

};
test.cpp

#include <iostream>
#include <string>
#include <cstdlib>
#include <vector>
#include "../tinyxml2.h"

#include "country.hpp"

using namespace tinyxml2;
using namespace std;

#define EXIT_ABNOEMAL(msg) {printf("%s\n", msg); return -1;}

//构造一个country
Country* getCountry(const string &name)
{
    auto country = new Country(name);

    City haerbing("哈尔滨");
    City daqing("大庆");
    Province heilongjing("黑龙江");
    heilongjing.vCities.push_back(haerbing);
    heilongjing.vCities.push_back(daqing);

    City guangzhou("广州");
    City shenzhen("深圳");
    City zhuhai("珠海");
    Province guangdong("广东");
    guangdong.vCities.push_back(guangzhou);
    guangdong.vCities.push_back(shenzhen);
    guangdong.vCities.push_back(zhuhai);

    City taibei("台北");
    City gaoxiong("高雄");
    Province taiwan("台湾");
    taiwan.vCities.push_back(gaoxiong);
    taiwan.vCities.push_back(taibei);

    City wulumuqi("乌鲁木齐");
    Province xinjiang("新疆");
    xinjiang.vCities.push_back(wulumuqi);
    
    country->vProvinces.push_back(xinjiang);
    country->vProvinces.push_back(heilongjing);
    country->vProvinces.push_back(guangdong);
    country->vProvinces.push_back(taiwan);
    
    return country;
}

//序列化对象到xml
int parseCountryToXml(Country *country, const string &filePath)
{
    XMLDocument doc;
    //调用country的序列化函数
    int ret = country->parseXML(doc, filePath);
    return ret;
}

//反序列化到对象
int readXMLToCountry(Country * country, const string &filePath)
{
    XMLDocument doc;
    //调用对象的反序列花方法
    int ret = country->convertXMLToObject(doc, filePath);
    return ret;
}

int main()
{
    const string fileName = "../test/country.xml";

    //将中国对象保存到xml中
    auto zhongguo = getCountry("zhongguo");
    int ret;
    ret = parseCountryToXml(zhongguo, fileName);
    if(ret)
    {
        EXIT_ABNOEMAL("convert to xml error!");
    }

    //从上面的xml中反序列化成china对象
    Country *china = new Country();
    ret = readXMLToCountry(china, fileName);
    if(ret)
    {
        EXIT_ABNOEMAL("convert to Object error!");
    }

    //输出china对象
    string s = china->toString();
    cout<<s<<"\n";

    //安全删除指针
    SAFE_DELETE(zhongguo);
    SAFE_DELETE(china);
    return 0;
}

结果:

 country.xml

<?xml version="1.0" encoding="UTF-8"?>
<country>
    <name>zhongguo</name>
    <province>
        <name>新疆</name>
        <cities>
            <city>乌鲁木齐</city>
        </cities>
    </province>
    <province>
        <name>黑龙江</name>
        <cities>
            <city>哈尔滨</city>
            <city>大庆</city>
        </cities>
    </province>
    <province>
        <name>广东</name>
        <cities>
            <city>广州</city>
            <city>深圳</city>
            <city>珠海</city>
        </cities>
    </province>
    <province>
        <name>台湾</name>
        <cities>
            <city>高雄</city>
            <city>台北</city>
        </cities>
    </province>
</country>


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值