VC++ 下使用 xml 文件导入导出数据
2008-07-29 21:57
671 查看
XML (eXtensible Markup Language) 是一种简单的数据存储语言,使用一系列简单的标记描述数据,虽然XML占用的空间比二进制数据要占用更多的空间,但XML极其简单易于掌握和使用。更重要的是,xml 可以描述非常复杂的数据结构,比如树状结构。
为了建立一个通用,易于扩展,易于使用的数据导入导出应用,首先得定义一些数据类型用于存储 int, float, string, array 等基本数据类型。
#pragma once
#include "Collection.h"
class CDataType
{
public:
CString Id;
CDataType(void) {}
virtual ~CDataType() {}
virtual char* GetTypeName() { return ""; }
virtual int& Integer() { ::AfxThrowInvalidArgException(); }
virtual float& Float() { ::AfxThrowInvalidArgException(); }
virtual CString& String() { ::AfxThrowInvalidArgException(); }
virtual CDataType& operator[](LPCTSTR key) { ::AfxThrowInvalidArgException(); }
virtual CDataType& operator[](int index) { ::AfxThrowInvalidArgException(); }
virtual bool IsCollection() { return false; }
virtual CString& ToXML(CString& s) { return s; }
};
class CIntegerType: public CDataType
{
int m_Object;
public:
CIntegerType(int value) { m_Object = value; }
virtual char* GetTypeName() { return "INT"; }
virtual int& Integer() { return m_Object; }
virtual CString& ToXML(CString& s) {
s.Format("<INT ID=/"%s/" V=/"%d/" />", Id, m_Object);
return s;
}
};
class CFloatType: public CDataType
{
float m_Object;
public:
CFloatType(float value) { m_Object = value; }
virtual char* GetTypeName() { return "FLOAT"; }
virtual float& Float() { return m_Object; }
virtual CString& ToXML(CString& s) {
s.Format("<FLOAT ID=/"%s/" V=/"%g/" />", Id, m_Object);
return s;
}
};
class CStringType: public CDataType
{
CString m_Object;
public:
CStringType(LPCTSTR value) { m_Object = value; }
virtual char* GetTypeName() { return "STR"; }
virtual CString& String() { return m_Object; }
virtual CString& ToXML(CString& s) {
s.Format("<STR ID=/"%s/" V=/"%s/" />", Id, m_Object);
return s;
}
};
class CStringArrayType: public CDataType
{
CArray<CString*, CString*> m_Object;
public:
CStringArrayType() {}
virtual char* GetTypeName() { return "STRs"; }
void Add(LPCTSTR value) { m_Object.Add(new CString(value)); }
CString& GetAt(int index) { return *m_Object[index]; }
int GetCount() { return (int) m_Object.GetCount(); }
virtual ~CStringArrayType(void) { for (int i=0; i<m_Object.GetCount(); i++) delete m_Object[i]; }
virtual CString& ToXML(CString& s) {
s.Format("<STRs ID=/"%s/"", Id);
for (int i=0; i<m_Object.GetCount(); i++) {
s.Format("%s V%d=/"%s/"", s, i, GetAt(i));
}
return s;
}
};
class CIntegerArrayType: public CDataType
{
CArray<int, int&> m_Object;
public:
virtual char* GetTypeName() { return "INTs"; }
int& GetAt(int index) { return m_Object[index]; }
void Add(int value) { m_Object.Add(value); }
int GetCount() { return (int) m_Object.GetCount(); }
virtual CString& ToXML(CString& s) {
s.Format("<INTs ID=/"%s/"", Id);
for (int i=0; i<m_Object.GetCount(); i++) {
s.Format("%s V%d=/"%d/"", s, i, GetAt(i));
}
return s;
}
};
class CFloatArrayType: public CDataType
{
CArray<float, float&> m_Object;
public:
virtual char* GetTypeName() { return "FLOATs"; }
void Add(float value) { m_Object.Add(value); }
float& GetAt(int index) { return m_Object[index]; }
int GetCount() { return (int) m_Object.GetCount(); }
virtual CString& ToXML(CString& s) {
s.Format("<INTs ID=/"%s/"", Id);
for (int i=0; i<m_Object.GetCount(); i++) {
s.Format("%s V%d=/"%g/"", s, i, GetAt(i));
}
return s;
}
};
class CCollectionType: public CDataType
{
CCollection<CDataType> m_Object;
public:
CCollectionType() {}
virtual ~CCollectionType(void) { DeleteAll(); }
virtual CCollectionType& Collection() { return *this; }
virtual char* GetTypeName() { return "SETs"; }
virtual bool IsCollection() { return true; }
void Add(LPCTSTR key, CDataType* object) { m_Object.Add(key, object)->Id = key; }
void Add(LPCTSTR key, int value) { m_Object.Add(key, new CIntegerType(value))->Id = key; }
void Add(LPCTSTR key, float value) { m_Object.Add(key, new CFloatType(value))->Id = key; }
void Add(LPCTSTR key, LPCTSTR value) { m_Object.Add(key, new CStringType(value))->Id = key; }
int GetCount() { return m_Object.GetCount(); }
CDataType& operator[](LPCTSTR key) { return m_Object[key]; }
CDataType& operator[](int index) { return m_Object[index]; }
CDataType* GetAt(LPCTSTR key) { return m_Object.GetAt(key); }
CDataType* GetAt(int index) { return m_Object.GetAt(index); }
void RemoveAll() { return m_Object.RemoveAll(); }
void DeleteAll() { return m_Object.DeleteAll(); }
virtual CString& ToXML(CString& s) {
s.Format("<SETs ID=/"%s/">", Id, m_Object);
return s;
}
};
CCollectionType 是一个可以使用字符名称以及索引查询的CDataType 集合类,由于CCollectionType 是从CDataType 派生,所以CcollectionType 可以被加入到CcollectionType 中,用以形成树状结构。
VC++ 下带有 xml 的解析 IXMLDOMDocument, 虽然没有 C# 下简单,但是在MSXML2 namespace 下的封装类,则相当简单.
bool CXMLFile::Load(LPCTSTR fileName, CCollectionType& collection)
{
try {
if FAILED(::CoInitialize(NULL))
return false;
MSXML2::IXMLDOMDocumentPtr pXMLDoc = NULL;
if FAILED(pXMLDoc.CreateInstance("Msxml2.DOMDocument.4.0"))
return false;
if (! pXMLDoc->load(CComVariant(fileName)))
return false;
MSXML2::IXMLDOMElementPtr pElement = pXMLDoc->documentElement;
if (collection.Id != pElement->nodeName.GetBSTR())
return false;
return ParseObjects(pElement->childNodes, collection);
}
catch (...) { return false; }
}
bool CXMLFile::ParseObjects(MSXML2::IXMLDOMNodeListPtr nodes, CCollectionType& collection)
{
try {
MSXML2::IXMLDOMNodePtr node;
int length = nodes->length;
for (long n=0; n<length; n++) {
node = nodes->item[n];
CString type(node->nodeName.GetBSTR());
if (node->attributes->length < 1) return false;
CComVariant id = node->attributes->item[0]->nodeValue;
if (type == "INT") {
if (node->attributes->length < 2) return false;
CComVariant value = node->attributes->item[1]->nodeValue;
int v = ::atoi((LPCTSTR) CString(value.bstrVal));
collection.Add(CString(id.bstrVal), v);
}
else if (type == "FLOAT") {
if (node->attributes->length < 2) return false;
CComVariant value = node->attributes->item[1]->nodeValue;
float v = (float) ::atof((LPSTR) value.bstrVal);
collection.Add(CString(id.bstrVal), v);
}
else if (type == "INTs") {
if (node->attributes->length < 2) return false;
CIntegerArrayType* v = new CIntegerArrayType;
int cout = node->attributes->length - 1;
for (int i=1; i<node->attributes->length; i++) {
CComVariant value = node->attributes->item[i]->nodeValue;
v->Add(::atoi((LPSTR) value.bstrVal));
}
collection.Add(CString(id.bstrVal), v);
}
else if (type == "STRs") {
if (node->attributes->length < 2) return false;
CStringArrayType* v = new CStringArrayType;
int cout = node->attributes->length - 1;
for (int i=1; i<node->attributes->length; i++) {
CComVariant value = node->attributes->item[i]->nodeValue;
v->Add(CString(value.bstrVal));
}
collection.Add(CString(id.bstrVal), v);
}
else if (type == "STR") {
if (node->attributes->length < 2) return false;
CComVariant value = node->attributes->item[1]->nodeValue;
collection.Add(CString(id.bstrVal), (LPCTSTR) CString(value.bstrVal));
}
else if (type == "SETs") {
CCollectionType* v = new CCollectionType();
collection.Add(CString(id.bstrVal), v);
if (! ParseObjects(node->childNodes, *v))
return false;
}
else {
}
}
}
catch(...) { return false; }
return true;
}
bool CXMLFile::Save(CStdioFile& file, CCollectionType& collection)
{
try {
m_IndentCount = 0;
file.WriteString("<");
file.WriteString(collection.Id);
file.WriteString(">/n");
SaveObjects(file, collection);
file.WriteString("</");
file.WriteString(collection.Id);
file.WriteString(">");
file.Close();
return true;
}
catch (...) { return false; }
}
bool CXMLFile::SaveObjects(CStdioFile& file, CCollectionType& collection)
{
try {
m_IndentCount++;
CString s;
for (int i=0; i<collection.GetCount(); i++) {
CDataType* v= collection.GetAt(i);
for (int n=0; n<m_IndentCount; n++)
file.WriteString(" ");
file.WriteString(v->ToXML(s) + "/n");
if (v->IsCollection()) {
SaveObjects(file, *(CCollectionType*) v);
for (int n=0; n<m_IndentCount; n++)
file.WriteString(" ");
file.WriteString("</SETs>/n");
}
}
m_IndentCount--;
return true;
}
catch (...) { return false; }
}
最终的使用变得非常简单:
CFileDialog openFile(TRUE, NULL, NULL, OFN_HIDEREADONLY,
_T("XML File (*.xml)|*.xml|All Files (*.*)|*.*||"), NULL);
if (openFile.DoModal() == IDOK) {
CXMLFile file;
CCollectionType collection;
collection.Id = _T("DEVICE");
if (! file.Load(openFile.GetFileName(), collection)) {
::MessageBox(NULL, _T(" Cannot open the file for write. "), NULL, MB_ICONSTOP | MB_OK);
return;
}
m_Text.SetWindowText(collection["APPLICATION"]["SYSTEM"]["VERSION"].String());
CString fileName = openFile.GetFileName() + "_";
CStdioFile outfile;
if( !outfile.Open(fileName, CFile::modeCreate|CFile::modeWrite|CFile::typeText)) {
::MessageBox(NULL, _T(" Cannot open the file for write. "), NULL, MB_ICONSTOP | MB_OK);
return;
}
file.Save(outfile, collection);
为了建立一个通用,易于扩展,易于使用的数据导入导出应用,首先得定义一些数据类型用于存储 int, float, string, array 等基本数据类型。
#pragma once
#include "Collection.h"
class CDataType
{
public:
CString Id;
CDataType(void) {}
virtual ~CDataType() {}
virtual char* GetTypeName() { return ""; }
virtual int& Integer() { ::AfxThrowInvalidArgException(); }
virtual float& Float() { ::AfxThrowInvalidArgException(); }
virtual CString& String() { ::AfxThrowInvalidArgException(); }
virtual CDataType& operator[](LPCTSTR key) { ::AfxThrowInvalidArgException(); }
virtual CDataType& operator[](int index) { ::AfxThrowInvalidArgException(); }
virtual bool IsCollection() { return false; }
virtual CString& ToXML(CString& s) { return s; }
};
class CIntegerType: public CDataType
{
int m_Object;
public:
CIntegerType(int value) { m_Object = value; }
virtual char* GetTypeName() { return "INT"; }
virtual int& Integer() { return m_Object; }
virtual CString& ToXML(CString& s) {
s.Format("<INT ID=/"%s/" V=/"%d/" />", Id, m_Object);
return s;
}
};
class CFloatType: public CDataType
{
float m_Object;
public:
CFloatType(float value) { m_Object = value; }
virtual char* GetTypeName() { return "FLOAT"; }
virtual float& Float() { return m_Object; }
virtual CString& ToXML(CString& s) {
s.Format("<FLOAT ID=/"%s/" V=/"%g/" />", Id, m_Object);
return s;
}
};
class CStringType: public CDataType
{
CString m_Object;
public:
CStringType(LPCTSTR value) { m_Object = value; }
virtual char* GetTypeName() { return "STR"; }
virtual CString& String() { return m_Object; }
virtual CString& ToXML(CString& s) {
s.Format("<STR ID=/"%s/" V=/"%s/" />", Id, m_Object);
return s;
}
};
class CStringArrayType: public CDataType
{
CArray<CString*, CString*> m_Object;
public:
CStringArrayType() {}
virtual char* GetTypeName() { return "STRs"; }
void Add(LPCTSTR value) { m_Object.Add(new CString(value)); }
CString& GetAt(int index) { return *m_Object[index]; }
int GetCount() { return (int) m_Object.GetCount(); }
virtual ~CStringArrayType(void) { for (int i=0; i<m_Object.GetCount(); i++) delete m_Object[i]; }
virtual CString& ToXML(CString& s) {
s.Format("<STRs ID=/"%s/"", Id);
for (int i=0; i<m_Object.GetCount(); i++) {
s.Format("%s V%d=/"%s/"", s, i, GetAt(i));
}
return s;
}
};
class CIntegerArrayType: public CDataType
{
CArray<int, int&> m_Object;
public:
virtual char* GetTypeName() { return "INTs"; }
int& GetAt(int index) { return m_Object[index]; }
void Add(int value) { m_Object.Add(value); }
int GetCount() { return (int) m_Object.GetCount(); }
virtual CString& ToXML(CString& s) {
s.Format("<INTs ID=/"%s/"", Id);
for (int i=0; i<m_Object.GetCount(); i++) {
s.Format("%s V%d=/"%d/"", s, i, GetAt(i));
}
return s;
}
};
class CFloatArrayType: public CDataType
{
CArray<float, float&> m_Object;
public:
virtual char* GetTypeName() { return "FLOATs"; }
void Add(float value) { m_Object.Add(value); }
float& GetAt(int index) { return m_Object[index]; }
int GetCount() { return (int) m_Object.GetCount(); }
virtual CString& ToXML(CString& s) {
s.Format("<INTs ID=/"%s/"", Id);
for (int i=0; i<m_Object.GetCount(); i++) {
s.Format("%s V%d=/"%g/"", s, i, GetAt(i));
}
return s;
}
};
class CCollectionType: public CDataType
{
CCollection<CDataType> m_Object;
public:
CCollectionType() {}
virtual ~CCollectionType(void) { DeleteAll(); }
virtual CCollectionType& Collection() { return *this; }
virtual char* GetTypeName() { return "SETs"; }
virtual bool IsCollection() { return true; }
void Add(LPCTSTR key, CDataType* object) { m_Object.Add(key, object)->Id = key; }
void Add(LPCTSTR key, int value) { m_Object.Add(key, new CIntegerType(value))->Id = key; }
void Add(LPCTSTR key, float value) { m_Object.Add(key, new CFloatType(value))->Id = key; }
void Add(LPCTSTR key, LPCTSTR value) { m_Object.Add(key, new CStringType(value))->Id = key; }
int GetCount() { return m_Object.GetCount(); }
CDataType& operator[](LPCTSTR key) { return m_Object[key]; }
CDataType& operator[](int index) { return m_Object[index]; }
CDataType* GetAt(LPCTSTR key) { return m_Object.GetAt(key); }
CDataType* GetAt(int index) { return m_Object.GetAt(index); }
void RemoveAll() { return m_Object.RemoveAll(); }
void DeleteAll() { return m_Object.DeleteAll(); }
virtual CString& ToXML(CString& s) {
s.Format("<SETs ID=/"%s/">", Id, m_Object);
return s;
}
};
CCollectionType 是一个可以使用字符名称以及索引查询的CDataType 集合类,由于CCollectionType 是从CDataType 派生,所以CcollectionType 可以被加入到CcollectionType 中,用以形成树状结构。
VC++ 下带有 xml 的解析 IXMLDOMDocument, 虽然没有 C# 下简单,但是在MSXML2 namespace 下的封装类,则相当简单.
bool CXMLFile::Load(LPCTSTR fileName, CCollectionType& collection)
{
try {
if FAILED(::CoInitialize(NULL))
return false;
MSXML2::IXMLDOMDocumentPtr pXMLDoc = NULL;
if FAILED(pXMLDoc.CreateInstance("Msxml2.DOMDocument.4.0"))
return false;
if (! pXMLDoc->load(CComVariant(fileName)))
return false;
MSXML2::IXMLDOMElementPtr pElement = pXMLDoc->documentElement;
if (collection.Id != pElement->nodeName.GetBSTR())
return false;
return ParseObjects(pElement->childNodes, collection);
}
catch (...) { return false; }
}
bool CXMLFile::ParseObjects(MSXML2::IXMLDOMNodeListPtr nodes, CCollectionType& collection)
{
try {
MSXML2::IXMLDOMNodePtr node;
int length = nodes->length;
for (long n=0; n<length; n++) {
node = nodes->item[n];
CString type(node->nodeName.GetBSTR());
if (node->attributes->length < 1) return false;
CComVariant id = node->attributes->item[0]->nodeValue;
if (type == "INT") {
if (node->attributes->length < 2) return false;
CComVariant value = node->attributes->item[1]->nodeValue;
int v = ::atoi((LPCTSTR) CString(value.bstrVal));
collection.Add(CString(id.bstrVal), v);
}
else if (type == "FLOAT") {
if (node->attributes->length < 2) return false;
CComVariant value = node->attributes->item[1]->nodeValue;
float v = (float) ::atof((LPSTR) value.bstrVal);
collection.Add(CString(id.bstrVal), v);
}
else if (type == "INTs") {
if (node->attributes->length < 2) return false;
CIntegerArrayType* v = new CIntegerArrayType;
int cout = node->attributes->length - 1;
for (int i=1; i<node->attributes->length; i++) {
CComVariant value = node->attributes->item[i]->nodeValue;
v->Add(::atoi((LPSTR) value.bstrVal));
}
collection.Add(CString(id.bstrVal), v);
}
else if (type == "STRs") {
if (node->attributes->length < 2) return false;
CStringArrayType* v = new CStringArrayType;
int cout = node->attributes->length - 1;
for (int i=1; i<node->attributes->length; i++) {
CComVariant value = node->attributes->item[i]->nodeValue;
v->Add(CString(value.bstrVal));
}
collection.Add(CString(id.bstrVal), v);
}
else if (type == "STR") {
if (node->attributes->length < 2) return false;
CComVariant value = node->attributes->item[1]->nodeValue;
collection.Add(CString(id.bstrVal), (LPCTSTR) CString(value.bstrVal));
}
else if (type == "SETs") {
CCollectionType* v = new CCollectionType();
collection.Add(CString(id.bstrVal), v);
if (! ParseObjects(node->childNodes, *v))
return false;
}
else {
}
}
}
catch(...) { return false; }
return true;
}
bool CXMLFile::Save(CStdioFile& file, CCollectionType& collection)
{
try {
m_IndentCount = 0;
file.WriteString("<");
file.WriteString(collection.Id);
file.WriteString(">/n");
SaveObjects(file, collection);
file.WriteString("</");
file.WriteString(collection.Id);
file.WriteString(">");
file.Close();
return true;
}
catch (...) { return false; }
}
bool CXMLFile::SaveObjects(CStdioFile& file, CCollectionType& collection)
{
try {
m_IndentCount++;
CString s;
for (int i=0; i<collection.GetCount(); i++) {
CDataType* v= collection.GetAt(i);
for (int n=0; n<m_IndentCount; n++)
file.WriteString(" ");
file.WriteString(v->ToXML(s) + "/n");
if (v->IsCollection()) {
SaveObjects(file, *(CCollectionType*) v);
for (int n=0; n<m_IndentCount; n++)
file.WriteString(" ");
file.WriteString("</SETs>/n");
}
}
m_IndentCount--;
return true;
}
catch (...) { return false; }
}
最终的使用变得非常简单:
CFileDialog openFile(TRUE, NULL, NULL, OFN_HIDEREADONLY,
_T("XML File (*.xml)|*.xml|All Files (*.*)|*.*||"), NULL);
if (openFile.DoModal() == IDOK) {
CXMLFile file;
CCollectionType collection;
collection.Id = _T("DEVICE");
if (! file.Load(openFile.GetFileName(), collection)) {
::MessageBox(NULL, _T(" Cannot open the file for write. "), NULL, MB_ICONSTOP | MB_OK);
return;
}
m_Text.SetWindowText(collection["APPLICATION"]["SYSTEM"]["VERSION"].String());
CString fileName = openFile.GetFileName() + "_";
CStdioFile outfile;
if( !outfile.Open(fileName, CFile::modeCreate|CFile::modeWrite|CFile::typeText)) {
::MessageBox(NULL, _T(" Cannot open the file for write. "), NULL, MB_ICONSTOP | MB_OK);
return;
}
file.Save(outfile, collection);
相关文章推荐
- 在Oracle表数据和xml文件间相互导入导出的PL/SQL 过程
- 解决 在Oracle表数据和xml文件间相互导入导出的PL/SQL 过程
- 对象文件[置顶] 如何在 ASM 存储中使用 Data Pump (expdp impdp)进行数据导出导入操作
- XML文件导入到DATASET并且增加数据后导出为XML
- 旗正规则管理器使用——导入xml文件数据
- java使用Xstream注解 解析xml文件 并将数据导入MySql数据库中
- 使用PHP导入Excel和导出数据为Excel文件
- mysql导入导出数据中文乱码解决方法小结(1、navicat导入问题已解决,创建连接后修改连接属性,选择高级->将使用Mysql字符集复选框去掉,下拉框选择GBK->导入sql文件OK;2、phpmyadmin显示乱码的问题也解决,两步:1.将sql文件以utf8的字符集编码另存,2.将文件中sql语句中的字段字符集编码改成utf8,导入OK)
- 使用POI实现在java程序中导入导出Excel文件数据
- laravel excel安装使用,导入(读)导出(数据写入文件)
- 在Oracle表数据和xml文件间相互导入导出的PL/SQL 过程
- 使用数据泵导出和导入文件大小差别很大
- 怎么样使用Navicat for MySQL 导出mysql中的数据和将sql数据库文件导入到mysql数据库中
- .NET使用NPOI将数据导出/导入到Excel文件介绍
- 怎么样使用Navicat for MySQL 导出mysql中的数据和将sql数据库文件导入到mysql数据库中
- 使用存储过程将数据以XML格式导出到XML文件
- 使用Oracle存储过程导入导出数据文件
- 收藏点以备后用数据库将数据导入导出xml文件
- Oracle 使用数据泵 expdp impdp 导入导出数据库“表空间”文件
- 在Oracle表数据和xml文件间相互导入导出