VC++ 下使用 xml 文件导入导出数据

本文介绍了如何在VC++环境下利用XML进行数据的导入和导出。通过定义不同数据类型如INT, FLOAT, STR等,并实现ToXML方法,实现了数据到XML的转换。同时,使用IXMLDOMDocument接口解析XML文件,将数据加载到CCollectionType集合类中,简化了操作。" 114295379,10700328,Java字符流详解:编码解码与缓冲流,"['Java IO', '字符输入流', '字符输出流', '编码转换', '缓冲流']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

   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);

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值