将数据库文件导出XML文件以及解析XML文件生成数据库文件的处理方法

思路:将数据库所有要导出的信息通过sql语句得到,存储到结构体中,然后将结构体的内容通过自定义的xml格式导出。

此方法使用的是TinyXML2库,TinyXML2是一个开源的解析XML的库,能够用于C++,能够在Windows或Linux中编译。这个解析库的模型通过解析XML文件,然后在内存中生成DOM模型,从而让我们很方便的遍历这棵XML树。

1、配置TimyXML2

这里下载,这里只需将头文件和CPP文件放到自己的项目当中即可。
在这里插入图片描述
项目结构如下:
在这里插入图片描述

2、使用TinyXML2创建XML文件

其实无非就是以下几个步骤,然后进行逻辑上的整合:

第一步:添加声明,xml声明包含了版本和编码格式

第二步:创建根节点

第三步:创建子节点

第四步:为子节点增加内容

第五步:为子节点增加属性

第六步:保存xml文件

下面是由数据库文件生成的xml结构,结构为:可以导出多个数据库,每个数据库包括多个表,每个表有多个列和行数据。

<?xml version="1.0" encoding="UTF-8"?>
<databases>
    <database>
        <name>DB1</name>
        <tables>
            <table>
                <name>TB1</name>
                <ddl>sql1</ddl>
                <columns>
                    <column>
                        <name>col1</name>
                        <type>int</type>
                    </column>
                </columns>
                <rows>
                    <row>
                        <value column="0">row1</value>
                    </row>
                </rows>
            </table>
        </tables>
    </database>
    <database>
        <name>DB1</name>
        <tables>
            <table>
                <name>TB1</name>
                <ddl>sql1</ddl>
                <columns>
                    <column>
                        <name>col1</name>
                        <type>int</type>
                    </column>
                </columns>
                <rows>
                    <row>
                        <value column="1" null="true"/>
                    </row>
                </rows>
            </table>
        </tables>
    </database>
</databases>

Export.cpp 代码如下:

#include <iostream>
#include <vector>
#include "tinyxml2.h"
using namespace std;
using namespace tinyxml2;

//全局变量(省事了)
tinyxml2::XMLDocument doc;

typedef struct
{
	string value;
	string colNum;
	string valNull;
}RowContent;

typedef struct
{
	vector<RowContent> rowContents;
}Row;

typedef struct
{
	string name;
	string type;
}Column;

typedef struct
{
	string name;				//数据表名
	string ddl;					//用来存放创建表的sql语句
	vector<Column> colunms;
	vector<Row> rows;
}Table;

typedef struct
{
	string name;				//数据库名
	vector<Table> tables;		//数据库表的集合
}Database;

//创建数据表行数据节点
tinyxml2::XMLElement * GenerateRowValueElements(RowContent rowContent)
{
	//行的父节点
	tinyxml2::XMLElement* childNodeRowValue = doc.NewElement("value");

	if (rowContent.value != "")
	{
		//为子节点增加内容
		tinyxml2::XMLText* ContentNodeRowValue = doc.NewText(rowContent.value.c_str());
		childNodeRowValue->InsertFirstChild(ContentNodeRowValue);

		//为子节点增加属性
		childNodeRowValue->SetAttribute("column", rowContent.colNum.c_str());
	}
	else
	{
		//为子节点增加属性
		childNodeRowValue->SetAttribute("column", rowContent.colNum.c_str());
		childNodeRowValue->SetAttribute("null", "true");
	}

	return childNodeRowValue;
}

//创建数据表行数据节点
tinyxml2::XMLElement * GenerateRowElements(Row row)
{
	//行的父节点
	tinyxml2::XMLElement* childNodeRow = doc.NewElement("row");

	//为Row添加子节点
	for (vector<RowContent>::iterator it = row.rowContents.begin(); it != row.rowContents.end(); ++it)
	{
		childNodeRow->InsertEndChild(GenerateRowValueElements(*it));
	}

	return childNodeRow;
}

//创建数据表列数据节点
tinyxml2::XMLElement * GenerateColunmElements(Column column)
{
	//列的父节点
	tinyxml2::XMLElement* childNodeColumn = doc.NewElement("column");

	//增加列名子节点
	tinyxml2::XMLElement* childNodeColName = doc.NewElement("name");
	//增加列属性子节点
	tinyxml2::XMLElement* childNodeType = doc.NewElement("type");

	//为子节点增加内容
	tinyxml2::XMLText* contentColName = doc.NewText(column.name.c_str());
	childNodeColName->InsertFirstChild(contentColName);

	tinyxml2::XMLText* contentType = doc.NewText(column.type.c_str());
	childNodeType->InsertFirstChild(contentType);

	childNodeColumn->InsertEndChild(childNodeColName);
	childNodeColumn->InsertEndChild(childNodeType);

	return childNodeColumn;
}

//创建数据表节点
tinyxml2::XMLElement * GenerateTableElements(Table table)
{
	//表的父节点
	tinyxml2::XMLElement* childNodeTb = doc.NewElement("table");

	//增加表名子节点
	tinyxml2::XMLElement* childNodeTbName = doc.NewElement("name");
	//增加创建表的sql语句子节点
	tinyxml2::XMLElement* childNodeDll = doc.NewElement("ddl");
	//增加表的列信息子节点
	tinyxml2::XMLElement* childNodeColumns = doc.NewElement("columns");
	//增加表的行数据子节点
	tinyxml2::XMLElement* childNodeRows = doc.NewElement("rows");

	//为子节点增加内容
	tinyxml2::XMLText* contentTbName = doc.NewText(table.name.c_str());
	childNodeTbName->InsertFirstChild(contentTbName);

	tinyxml2::XMLText* contentDll = doc.NewText(table.ddl.c_str());
	childNodeDll->InsertFirstChild(contentDll);

	childNodeTb->InsertEndChild(childNodeTbName);
	childNodeTb->InsertEndChild(childNodeDll);
	childNodeTb->InsertEndChild(childNodeColumns);
	childNodeTb->InsertEndChild(childNodeRows);

	//为Columns添加子节点
	for (vector<Column>::iterator it = table.colunms.begin(); it != table.colunms.end(); ++it)
	{
		childNodeColumns->InsertEndChild(GenerateColunmElements(*it));
	}

	//为Rows添加子节点
	for (vector<Row>::iterator it = table.rows.begin(); it != table.rows.end(); ++it)
	{
		childNodeRows->InsertEndChild(GenerateRowElements(*it));
	}

	return childNodeTb;
}

//创建数据库节点
tinyxml2::XMLElement * GenerateDataBaseElements(Database database)
{
	//数据库的父节点
	tinyxml2::XMLElement* childNodeDB = doc.NewElement("database");
	//数据库名称子节点
	tinyxml2::XMLElement* childNodeDBName = doc.NewElement("name");
	//数据库表子节点
	tinyxml2::XMLElement* childNodeDBTables = doc.NewElement("tables");
	//为子节点增加内容
	tinyxml2::XMLText* contentDBName = doc.NewText(database.name.c_str());
	childNodeDBName->InsertFirstChild(contentDBName);

	childNodeDB->InsertEndChild(childNodeDBName);
	childNodeDB->InsertEndChild(childNodeDBTables);

	//添加database数组子节点
	for (vector<Table>::iterator it = database.tables.begin(); it != database.tables.end(); ++it)
	{
		childNodeDBTables->InsertEndChild(GenerateTableElements(*it));
	}

	return childNodeDB;
}

void GenerateXMLDocument(vector<Database> VecDataBases)
{
	//1.添加声明
	tinyxml2::XMLDeclaration* declaration = doc.NewDeclaration();
	doc.InsertFirstChild(declaration);

	//2.创建根节点
	tinyxml2::XMLElement* root = doc.NewElement("databases");
	doc.InsertEndChild(root);

	//3.添加database数组子节点
	for (vector<Database>::iterator it = VecDataBases.begin(); it != VecDataBases.end(); ++it)
	{
		root->InsertEndChild(GenerateDataBaseElements(*it));
	}

	//4.保存xml文件
	doc.SaveFile("C:/Users/Administrator/Desktop/DataBaseXML.xml");

	//如果重复生成的话,全局变量一直存在,第二次生成会导致内容重复,所以需要清理,当然,局部变量的话不会存在这样的问题
	doc.Clear();
}

int main()
{
	Database database0;
	database0.name = "DB1";

	Table table0;
	table0.name = "TB1";
	table0.ddl = "sql1";

	Column colunm0;
	colunm0.name = "col1";
	colunm0.type = "int";

	Row row0;

	RowContent rowContent0;
	rowContent0.value = "row1";
	rowContent0.colNum = "0";

	row0.rowContents.push_back(rowContent0);
	table0.rows.push_back(row0);
	table0.colunms.push_back(colunm0);
	database0.tables.push_back(table0);

	/**********************/
	Database database1;
	database1.name = "DB1";

	Table table1;
	table1.name = "TB1";
	table1.ddl = "sql1";

	Column colunm1;
	colunm1.name = "col1";
	colunm1.type = "int";

	Row row1;

	RowContent rowContent1;
	rowContent1.value = "";
	rowContent1.colNum = "1";

	row1.rowContents.push_back(rowContent1);
	table1.rows.push_back(row1);
	table1.colunms.push_back(colunm1);
	database1.tables.push_back(table1);

	/**********************/
	vector<Database> VecDataBases;
	VecDataBases.push_back(database0);
	VecDataBases.push_back(database1);

	GenerateXMLDocument(VecDataBases);
	return 0;
}

解释一下几个函数:

FirstChildElement(const char* value=0):获取第一个值为value的子节点,value默认值为空,则返回第一个子节点。
 
RootElement():获取根节点,相当于FirstChildElement的空参数版本;
 
const XMLAttribute* FirstAttribute() const:获取第一个属性值;
 
XMLHandle NextSiblingElement( const char* _value=0 ) :获得下一个兄弟节点。

3、解析上面创建的xml

对上面的第2节中的xml文件进行解析。

第一步,加载xml文件

第二步,找到根节点

第三步,获取子节点信息

Import.cpp代码如下:

#include <iostream>
#include <vector>
#include "tinyxml2.h"
using namespace std;
using namespace tinyxml2;

tinyxml2::XMLDocument doc;

typedef struct
{
	string value;
}RowContent;

typedef struct
{
	vector<RowContent> rowContents;
}Row;

typedef struct
{
	string ddl;
	vector<Row> rows;
}Table;

typedef struct
{
	string name;
	vector<Table> tables;
}Database;

//解析xml文件
void DP(vector<Database> & DataBases)
{
	{
		/*if (!root)
		{
			return;
		}

		const char* content;
		content = root->GetText();
		if (content)
		{
			cout << content << endl;
		}

		DP(root->FirstChildElement());

		DP(root->NextSiblingElement());*/
	}
	XMLDocument doc;
	doc.LoadFile("C:/Users/Administrator/Desktop/DataBaseXML.xml");
	XMLElement *XMLdataBases = doc.RootElement();
	XMLElement *XMLdataBase = XMLdataBases->FirstChildElement("database");

	while (XMLdataBase)
	{
		XMLElement *DBName = XMLdataBase->FirstChildElement("name");

		Database database;
		database.name = (string)DBName->GetText();

		XMLElement *DBTables = XMLdataBase->FirstChildElement("tables");
		XMLElement *DBTable = DBTables->FirstChildElement("table");

		while (DBTable)
		{
			XMLElement *XMLddl = DBTable->FirstChildElement("ddl");

			Table table;
			table.ddl = (string)XMLddl->GetText();

			XMLElement *DBRows = DBTable->FirstChildElement("rows");
			XMLElement *DBRow = DBRows->FirstChildElement("row");

			while (DBRow)
			{
				Row row;

				XMLElement *XMLRowValue = DBRow->FirstChildElement("value");
				while (XMLRowValue)
				{
					RowContent rowContent;

					const XMLAttribute *nullValue = XMLRowValue->FirstAttribute()->Next();
					if (!nullValue)
					{
						rowContent.value = (string)XMLRowValue->GetText();
					}
					else
					{
						rowContent.value = "NULL";
					}

					row.rowContents.push_back(rowContent);
					XMLRowValue = XMLRowValue->NextSiblingElement();
				}

				table.rows.push_back(row);
				DBRow = DBRow->NextSiblingElement();
			}
			database.tables.push_back(table);
			DBTable = DBTable->NextSiblingElement();
		}

		DataBases.push_back(database);
		//下一个兄弟节点
		XMLdataBase = XMLdataBase->NextSiblingElement();
	}
}

int main()
{
	vector<Database> DataBases;

	DP(DataBases);

	for (vector<Database>::iterator it = DataBases.begin(); it != DataBases.end(); ++it)
	{
		Database database = *it;

		cout << database.name.c_str() << endl;

		for (vector<Table>::iterator it1 = database.tables.begin(); it1 != database.tables.end(); ++it1)
		{
			Table table = *it1;
			cout << table.ddl.c_str() << endl;

			for (vector<Row>::iterator it2 = table.rows.begin(); it2 != table.rows.end(); ++it2)
			{
				Row row = *it2;
				for (vector<RowContent>::iterator it3 = row.rowContents.begin(); it3 != row.rowContents.end(); ++it3)
				{
					RowContent rowContent = *it3;
					cout << rowContent.value.c_str();
				}
				cout << endl;
			}
		}
		cout << endl;
	}

	system("pause");
	return 0;
}

提示:

只需要将数据库信息提取出来,把结构体Database的内容填充完整,最后将得到的Database数组传到方法中,即可得到相应文件。
 
可能会涉及到的sql语句:
   SELECT * FROM sqlite_master WHERE type=‘table’; //获得当前数据库所有数据表的名字以及创建表的sql语句
   PRAGMA table_info(‘tablename’); //获得所有表的列信息
 
输出的内容不全,按照自己需求自定义输出内容!

更多推荐