C++解析XML, 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 vCities;Province(const std::string &name):name(name){}Province(){}
};class Country
{
public:std::string name;std::vector vProvinces;public:Country(const std::string &name):name(name){}Country(){}/*** 将本类的成员变量序列化到一个固定格式的xml文件中* 采用模板,可以不需要写 tinyxml2的头文件*/templateint parseXML(T &doc, const std::string &fileName){//xml头//R"(string)", string可以以原来的形式存在,“” 不需要转义符const char *declaration = R"()";//将字符串解析到dom对象中doc.Parse(declaration);//new 一个 key//序列化std::string name;auto roof = doc.NewElement("country");auto keyCountryName = doc.NewElement("name");//插入valuekeyCountryName->InsertEndChild(doc.NewText(name.c_str()));//插入>roof->InsertEndChild(keyCountryName);doc.InsertEndChild(roof);//序列化std::vector 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 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文件成一个对象templateint 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 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 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; }//序列化对象到stringstd::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
#include
#include
#include
#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 &#61; "../test/country.xml";//将中国对象保存到xml中auto zhongguo &#61; getCountry("zhongguo");int ret;ret &#61; parseCountryToXml(zhongguo, fileName);if(ret){EXIT_ABNOEMAL("convert to xml error!");}//从上面的xml中反序列化成china对象Country *china &#61; new Country();ret &#61; readXMLToCountry(china, fileName);if(ret){EXIT_ABNOEMAL("convert to Object error!");}//输出china对象string s &#61; china->toString();cout<}
结果&#xff1a;country.xml
zhongguo新疆乌鲁木齐黑龙江哈尔滨大庆广东广州深圳珠海台湾高雄台北