今天实战用boost库中的方法,读取xml格式文件。
博文中涉及到xml的解析,xml内容的提取,数据库的创建,已经向数据库中添加表,并向表中写内容。
xml文件所在的目录:
xml的文件内容:
具体代码实现:
#include<iostream>
//起名
namespace bfs = boost::filesystem;
//创建一个db,我们使用sqlite这种小型数据库,指针使用unique指针。
std::unique_ptr<SQLite::Database> createDb(const bfs::Path& dbPath)
{
if(bfs::exists(dbPath)) //判断是否存在重名的db,如果有,删除后再创建。
bfs::remove(dbPath);
//根据path创建一个unique指向的SQLite类型的数据库
auto db = std::unique_shared<SQLite::Datebase>(dbPath.string(), SQLite::OPEN_READWRITE);
return db;
}
//提取数据。这里第二参数是一个std::funtion,后面得总结下这玩意的用法。
int extractDataFromXml(const std::string& fileName, std::function<void(std::string &id, std::string data)> function)
{
//要读取一个文件的内容,这儿得使用stream流来读取。
std::ifstream file(fileName.c_str());
//然后从流中获取数据!boost库为我们提供了从xml文件中读取文件的方法。已经存储的对象。
boost::property_tree::ptree tree;
boost::property_tree::xml_parser::read_xml(file, tree);
//我们获取xml文件中的objects关键字
auto objects = tree.get_child("objects");
//objects里面有无数个子项,现在循环遍历
for(auto& object : objects)
{
const auto name = it->first;
auto& data = it->second; //当我们获取容器或者其他存储空间的内容时,我们不知道里面的大小的时候,应该以引用的兴趣是获取。
if (name == "ggg") //找到ggg的这一集配置
{
auto itemId = data.get_child("itemId").get_value<std::string>();
auto base64Data = data.get_child("data").get_value<std::string>();
auto resData = Base64Decode2(base64Data);
try
{
//我们这里直接调用我们外面声明的lambda函数。
func(std::move(itemId), std::move(resData)); //std的move方法使用,cppreferece查看一下。好像是不拷贝直接移除。
}
catch(...)
{
std::cout<<"hhh"<<std::endl;
}
}
}
}
void xml2Dbfile(const boost::filesystem::path& xmlsDir, const boost::filesystem::Path& fileDbPath)
//path所在的命名空间名太长了,我们t给起个短点的名字
{
//首先,第一步肯定得先创建一个db,应为我们这个path的最后一级db目前还不存在
auto db = createDb(fileDbPath);
//因为目录中有不止一个xml文件,所以我们需要循环读取。
//需要知道:directory_iterator() BOOST_NOEXCEPT {} // creates the "end" iterator
for(bfs::directory_iterator iter(xmlsDir); iter != bfs::directory_iterator(); ++iter)
{
//首先该文件一定要是有规律的文件的
if(bfs::is_regular_file(iter->path()))
{
//其次,该文件要是xml格式的文件
if(iter->path().extension() == ".xml")
{
//接下来,提取xml文件中的内容,提取之后写到db中,写成一张表
const auto infos = extractDataFromXml(iter->path().string(), [&](const std::string& dataId, const std::string& dataValue)
{
//在db中插入一张表,表名叫个fileData吧就
SQLite::Statement writer(*db, "insert into fileData(handle, data) values(:dataId, :dataValue)");
writer.bind(":dataId", dataID);
writer.bind(":dataValue", dataValue);
//执行语句
writer.exec();
});
}
}
}
}
int main()
{
const auto xmlsDir = "G:\\xmls"; //首先我们定义需要转化的xml文件所在的目录
const auto fileDbPath = "G:\\dbs\\fileDB"; //然后定义xml文件生成的db的path
try
{
xml2Dbfile(xmlsDir, fileDbPath);
}
}