XML,可扩展的标识语言(eXtensible Markup Language),具有多种优势,所以现在被广泛使用,本文通过一个简单的例子来实现对XML文件的保存和读取操作。
使用工具:VS2008
使用语言:C++
开发步骤:
1.新建对话框程序
2.添加XML相关类
见附件!
3.添加XML操作类和相关数据结构
XmlDataInfo.h
#pragma once
#define SEX_BOY 0
#define SEX_GIRL 1
struct tXML_DATA_INFO
{
CString sName;//姓名
DWORD dwNumber;//编号
BOOL bSex;//性别
UCHAR ucAge;//年龄
DOUBLE dbScore;//分数
tXML_DATA_INFO()
{
sName = _T("");
dwNumber= 0;
bSex = SEX_BOY;
ucAge = 0;
dbScore = 0;
}
tXML_DATA_INFO& operator = (tXML_DATA_INFO& item)
{
sName = item.sName;
dwNumber= item.dwNumber;
bSex = item.bSex;
ucAge = item.ucAge;
dbScore = item.dbScore;
return* this;
}
};
typedef CArray<tXML_DATA_INFO,tXML_DATA_INFO&> ArrXmlDataInfoNodes;
class CXmlDataInfo
{
public:
CXmlDataInfo(void);
~CXmlDataInfo(void);
public:
ArrXmlDataInfoNodes m_arrXmlDataInfo;
DWORD LoadFile(CString sFilePathName);
DWORD SaveFile(CString sFilePathName);
};
XmlDataInfo.cpp
#include "StdAfx.h"
#include "XmlDataInfo.h"
#include "Markup.h"
//根元素
#define XML_DATA_INFO_ROOT _T("XmlDataInfoRoot")
//结构信息
#define XML_DATA_INFO_LIST _T("XmlDataInfoList")
#define XML_DATA_INFO_ITEM _T("XmlDataInfoItem")
#define XML_DATA_INFO_NAME _T("XmlDataInfoName")
#define XML_DATA_INFO_NUM _T("XmlDataInfoNum")
#define XML_DATA_INFO_SEX _T("XmlDataInfoSex")
#define XML_DATA_INFO_AGE _T("XmlDataInfoAge")
#define XML_DATA_INFO_SCORE _T("XmlDataInfoScore")
CString DoubleToString(double dbValue)
{
CString str = "";
str.Format("%f",dbValue);
str.TrimRight("0");
str.TrimRight(".");
return str;
}
CXmlDataInfo::CXmlDataInfo(void)
{
m_arrXmlDataInfo.RemoveAll();
}
CXmlDataInfo::~CXmlDataInfo(void)
{
}
DWORD CXmlDataInfo::LoadFile(CString sFilePathName)
{
CMarkup xml;
xml.Load(sFilePathName);
tXML_DATA_INFO data;
m_arrXmlDataInfo.RemoveAll();
while(xml.FindChildElem(XML_DATA_INFO_LIST))
{
xml.IntoElem();
while(xml.FindChildElem(XML_DATA_INFO_ITEM))
{
xml.IntoElem();
data.sName = xml.GetAttrib(XML_DATA_INFO_NAME);
data.dwNumber = strtoul(xml.GetAttrib(XML_DATA_INFO_NUM),NULL,10);
data.bSex = atoi((LPSTR)(LPCTSTR)xml.GetAttrib(XML_DATA_INFO_SEX));
data.ucAge = atoi((LPSTR)(LPCTSTR)xml.GetAttrib(XML_DATA_INFO_AGE));
data.dbScore = atof((LPSTR)(LPCTSTR)xml.GetAttrib(XML_DATA_INFO_SCORE));
xml.OutOfElem();
m_arrXmlDataInfo.Add(data);
}
xml.OutOfElem();
}
return 0;
}
DWORD CXmlDataInfo::SaveFile(CString sFilePathName)
{
CMarkup xml;
xml.AddElem(XML_DATA_INFO_ROOT);//根元素
int i=0, cnt=0;
CString str = _T("");
cnt = m_arrXmlDataInfo.GetSize();
xml.AddChildElem(XML_DATA_INFO_LIST);
xml.IntoElem();
for(i=0; i<cnt; i++)
{
xml.AddChildElem(XML_DATA_INFO_ITEM);
xml.IntoElem();
xml.SetAttrib(XML_DATA_INFO_NAME, m_arrXmlDataInfo[i].sName);
xml.SetAttrib(XML_DATA_INFO_NUM, m_arrXmlDataInfo[i].dwNumber);
xml.SetAttrib(XML_DATA_INFO_SEX, m_arrXmlDataInfo[i].bSex);
xml.SetAttrib(XML_DATA_INFO_AGE, m_arrXmlDataInfo[i].ucAge);
xml.SetAttrib(XML_DATA_INFO_SCORE, DoubleToString(m_arrXmlDataInfo[i].dbScore));
xml.OutOfElem();
}
xml.OutOfElem();
bool bSuccess = xml.Save(sFilePathName);
if(!bSuccess)
{
return 1;
}
return 0;
}
4.添加数据编辑和显示界面
DataDlg.h
#pragma once
#include "afxwin.h"
#include "XmlDataInfo.h"
// CDataDlg 对话框
class CDataDlg : public CDialog
{
DECLARE_DYNAMIC(CDataDlg)
public:
CDataDlg(CWnd* pParent = NULL); // 标准构造函数
virtual ~CDataDlg();
// 对话框数据
enum { IDD = IDD_DIALOG_DATA };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
DECLARE_MESSAGE_MAP()
public:
CString m_sName;
DWORD m_dwNumber;
UCHAR m_ucAge;
DOUBLE m_dbScore;
BOOL m_bSex;
afx_msg void OnBnClickedRadioBoy();
afx_msg void OnBnClickedRadioGirl();
afx_msg void OnBnClickedOk();
afx_msg void OnBnClickedCancel();
virtual BOOL OnInitDialog();
tXML_DATA_INFO m_data;
};
DataDlg.cpp
// DataDlg.cpp : 实现文件
//
#include "stdafx.h"
#include "FileXmlDemo.h"
#include "DataDlg.h"
// CDataDlg 对话框
IMPLEMENT_DYNAMIC(CDataDlg, CDialog)
CDataDlg::CDataDlg(CWnd* pParent /*=NULL*/)
: CDialog(CDataDlg::IDD, pParent)
{
m_sName = _T("");
m_dwNumber = 0;
m_ucAge = 0;
m_dbScore = 0;
m_bSex = 0;
}
CDataDlg::~CDataDlg()
{
}
void CDataDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT_NAME, m_sName);
DDX_Text(pDX, IDC_EDIT_NUM, m_dwNumber);
DDX_Text(pDX, IDC_EDIT_AGE, m_ucAge);
DDX_Text(pDX, IDC_EDIT_SCORE, m_dbScore);
}
BEGIN_MESSAGE_MAP(CDataDlg, CDialog)
ON_BN_CLICKED(IDC_RADIO_BOY, &CDataDlg::OnBnClickedRadioBoy)
ON_BN_CLICKED(IDC_RADIO_GIRL, &CDataDlg::OnBnClickedRadioGirl)
ON_BN_CLICKED(IDOK, &CDataDlg::OnBnClickedOk)
ON_BN_CLICKED(IDCANCEL, &CDataDlg::OnBnClickedCancel)
END_MESSAGE_MAP()
// CDataDlg 消息处理程序
BOOL CDataDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: 在此添加额外的初始化
UpdateData(TRUE);
m_sName = m_data.sName;
m_dwNumber = m_data.dwNumber;
m_ucAge = m_data.ucAge;
m_dbScore = m_data.dbScore;
m_bSex = m_data.bSex;
if(0 == m_bSex)
{
((CButton*)GetDlgItem(IDC_RADIO_BOY))->SetCheck(TRUE);
((CButton*)GetDlgItem(IDC_RADIO_GIRL))->SetCheck(FALSE);
}
else if(1 == m_bSex)
{
((CButton*)GetDlgItem(IDC_RADIO_BOY))->SetCheck(FALSE);
((CButton*)GetDlgItem(IDC_RADIO_GIRL))->SetCheck(TRUE);
}
UpdateData(FALSE);
return TRUE; // return TRUE unless you set the focus to a control
// 异常: OCX 属性页应返回 FALSE
}
void CDataDlg::OnBnClickedRadioBoy()
{
// TODO: 在此添加控件通知处理程序代码
m_bSex = 0;
}
void CDataDlg::OnBnClickedRadioGirl()
{
// TODO: 在此添加控件通知处理程序代码
m_bSex = 1;
}
void CDataDlg::OnBnClickedOk()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);
m_data.sName = m_sName;
m_data.dwNumber = m_dwNumber;
m_data.bSex = m_bSex;
m_data.ucAge = m_ucAge;
m_data.dbScore = m_dbScore;
UpdateData(FALSE);
OnOK();
}
void CDataDlg::OnBnClickedCancel()
{
// TODO: 在此添加控件通知处理程序代码
OnCancel();
}
5.数据操作界面
FileXmlDemoDlg.h
public:
CXmlDataInfo m_xml;
CListCtrl m_list;
afx_msg void OnBnClickedBtnXmlLoad();
afx_msg void OnBnClickedBtnXmlSave();
afx_msg void OnBnClickedBtnXmlAdd();
afx_msg void OnBnClickedBtnXmlEdit();
afx_msg void OnBnClickedBtnXmlDelete();
void UpdateListData(void);
int m_nSelectItem;
afx_msg void OnNMClickList1(NMHDR *pNMHDR, LRESULT *pResult);
FileXmlDemoDlg.cpp
BOOL CFileXmlDemoDlg::OnInitDialog()
{
CDialog::OnInitDialog();
//属性设置
m_list.ModifyStyle(LVS_TYPEMASK,LVS_REPORT & LVS_TYPEMASK | LVS_SINGLESEL);//important for show
DWORD dwStyle = m_list.GetExtendedStyle();
m_list.SetExtendedStyle(dwStyle | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
//设置行距
CImageList image;
image.Create(1,20,ILC_COLOR24 | ILC_MASK,4,0);
m_list.SetImageList(&image,LVSIL_SMALL);
//设置字体
CFont font;
font.CreateFont(
16,
0,
0,
0,
FW_NORMAL,
FALSE,
FALSE,
0,
ANSI_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
DEFAULT_PITCH | FF_SWISS,
_T("宋体"));
m_list.SetFont(&font);
m_list.GetHeaderCtrl()->SetFont(&font);
//标题栏
m_list.InsertColumn(0,_T("姓名"),LVCFMT_LEFT,100,0);
m_list.InsertColumn(1,_T("编号"),LVCFMT_LEFT,100,0);
m_list.InsertColumn(2,_T("性别"),LVCFMT_LEFT,100,0);
m_list.InsertColumn(3,_T("年龄"),LVCFMT_LEFT,100,0);
m_list.InsertColumn(4,_T("分数"),LVCFMT_LEFT,100,0);
m_nSelectItem = -1;
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
void CFileXmlDemoDlg::OnBnClickedBtnXmlLoad()
{
// TODO: 在此添加控件通知处理程序代码
CString sFilePathName = _T("");
CString str = _T(""), s = _T("");
CString sFileType = _T("");
str = _T("xml");
s = _T("xml files(*.xml)|*.xml|所有文件(*.*)|*.*||");
CFileDialog fd(TRUE,str,NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR,s,NULL);
if(IDOK == fd.DoModal())
{
sFilePathName = fd.GetPathName();
sFileType = fd.GetFileExt();
if("xml" == sFileType)
{
m_xml.LoadFile(sFilePathName);
UpdateListData();//更新界面
MessageBox(_T("打开文件成功!"));
}
else
{
MessageBox(_T("打开文件失败!"));
}
}
}
void CFileXmlDemoDlg::OnBnClickedBtnXmlSave()
{
// TODO: 在此添加控件通知处理程序代码
CString sFilePathName = _T("");
CString str = _T(""), s = _T("");
CString sFileType = _T("");
str = _T("xml");
s = _T("xml files(*.xml)|*.xml|所有文件(*.*)|*.*||");
CFileDialog fd(FALSE,str,NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR,s,NULL);
if(IDOK == fd.DoModal())
{
sFilePathName = fd.GetPathName();
if(-1 == sFilePathName.Find(".xml"))
{
sFilePathName = sFilePathName + ".xml";
}
m_xml.SaveFile(sFilePathName);
MessageBox(_T("保存文件成功!"));
}
}
void CFileXmlDemoDlg::OnBnClickedBtnXmlAdd()
{
// TODO: 在此添加控件通知处理程序代码
//tXML_DATA_INFO m_data;
CDataDlg dlg;
if(IDOK == dlg.DoModal())
{
m_xml.m_arrXmlDataInfo.Add(dlg.m_data);
UpdateListData();
}
}
void CFileXmlDemoDlg::OnBnClickedBtnXmlEdit()
{
// TODO: 在此添加控件通知处理程序代码
if(-1 == m_nSelectItem)
{
return;
}
CDataDlg dlg;
dlg.m_data = m_xml.m_arrXmlDataInfo[m_nSelectItem];
if(IDOK == dlg.DoModal())
{
m_xml.m_arrXmlDataInfo[m_nSelectItem] = dlg.m_data;
UpdateListData();
}
}
void CFileXmlDemoDlg::OnBnClickedBtnXmlDelete()
{
// TODO: 在此添加控件通知处理程序代码
if(-1 == m_nSelectItem)
{
return;
}
m_list.DeleteItem(m_nSelectItem);
m_xml.m_arrXmlDataInfo.RemoveAt(m_nSelectItem);
m_nSelectItem = -1;
}
void CFileXmlDemoDlg::UpdateListData(void)
{
m_list.DeleteAllItems();
CString str = _T("");
BOOL bSex = 0;
int cnt = m_xml.m_arrXmlDataInfo.GetSize();
for(int i=0; i<cnt; i++)
{
//姓名
m_list.InsertItem(i,m_xml.m_arrXmlDataInfo[i].sName);
//编号
str.Format("%d",m_xml.m_arrXmlDataInfo[i].dwNumber);
m_list.SetItemText(i,1,str);
//性别
bSex = m_xml.m_arrXmlDataInfo[i].bSex;
if(SEX_BOY == bSex)
{
str = _T("男");
}
else if(SEX_GIRL == bSex)
{
str = _T("女");
}
else
{
str = _T("--");
}
m_list.SetItemText(i,2,str);
//年龄
str.Format("%d",m_xml.m_arrXmlDataInfo[i].ucAge);
m_list.SetItemText(i,3,str);
//分数
str.Format("%f",m_xml.m_arrXmlDataInfo[i].dbScore);
m_list.SetItemText(i,4,str);
}
}
void CFileXmlDemoDlg::OnNMClickList1(NMHDR *pNMHDR, LRESULT *pResult)
{
//LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<NMITEMACTIVATE>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
CPoint CursorPoint;
if(!GetCursorPos(&CursorPoint))
{
return;
}
if(-1 == pNMListView->iItem)
{
m_nSelectItem = -1;
return;
}
else
{
m_nSelectItem = pNMListView->iItem;
}
*pResult = 0;
}
6.文档结构
7.效果演示
运行程序
打开文件
添加数据
修改数据
保存文件
删除数据
打开xml文件,查看数据
记事本打开效果
浏览器打开效果
附:
XML类
该类摘自网络
Markup.h
// Markup.h: interface for the CMarkup class.
//
// Markup Release 8.2
// Copyright (C) 1999-2006 First Objective Software, Inc. All rights reserved
// Go to www.firstobject.com for the latest CMarkup and EDOM documentation
// Use in commercial applications requires written permission
// This software is provided "as is", with no warranty.
#if !defined(AFX_MARKUP_H__948A2705_9E68_11D2_A0BF_00105A27C570__INCLUDED_)
#define AFX_MARKUP_H__948A2705_9E68_11D2_A0BF_00105A27C570__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#pragma warning(disable:4996) // suppress VS 2005 deprecated function warnings
#endif // _MSC_VER > 1000
#ifdef _DEBUG
#define _DS(i) (i?&((LPCTSTR)m_strDoc)[m_aPos[i].nStart]:0)
#define MARKUP_SETDEBUGSTATE m_pMainDS=_DS(m_iPos); m_pChildDS=_DS(m_iPosChild)
#else
#define MARKUP_SETDEBUGSTATE
#endif
class CMarkup
{
public:
CMarkup() { SetDoc( NULL ); InitDocFlags(); };
CMarkup( LPCTSTR szDoc ) { SetDoc( szDoc ); InitDocFlags(); };
CMarkup( int nFlags ) { SetDoc( NULL ); m_nFlags = nFlags; };
CMarkup( const CMarkup& markup ) { *this = markup; };
void operator=( const CMarkup& markup );
~CMarkup() {};
// Navigate
bool Load( LPCTSTR szFileName );
bool SetDoc( LPCTSTR szDoc );
bool IsWellFormed();
bool FindElem( LPCTSTR szName=NULL );
bool FindChildElem( LPCTSTR szName=NULL );
bool IntoElem();
bool OutOfElem();
void ResetChildPos() { x_SetPos(m_iPosParent,m_iPos,0); };
void ResetMainPos() { x_SetPos(m_iPosParent,0,0); };
void ResetPos() { x_SetPos(0,0,0); };
CString GetTagName() const;
CString GetChildTagName() const { return x_GetTagName(m_iPosChild); };
CString GetData() const { return x_GetData(m_iPos); };
CString GetChildData() const { return x_GetData(m_iPosChild); };
CString GetElemContent() const { return x_GetElemContent(m_iPos); };
CString GetAttrib( LPCTSTR szAttrib ) const { return x_GetAttrib(m_iPos,szAttrib); };
CString GetChildAttrib( LPCTSTR szAttrib ) const { return x_GetAttrib(m_iPosChild,szAttrib); };
CString GetAttribName( int n ) const;
int FindNode( int nType=0 );
int GetNodeType() { return m_nNodeType; };
bool SavePos( LPCTSTR szPosName=_T("") );
bool RestorePos( LPCTSTR szPosName=_T("") );
const CString& GetError() const { return m_strError; };
int GetDocFlags() const { return m_nFlags; };
void SetDocFlags( int nFlags ) { m_nFlags = nFlags; };
enum MarkupDocFlags
{
MDF_IGNORECASE = 8,
};
enum MarkupNodeFlags
{
MNF_WITHCDATA = 0x01,
MNF_WITHNOLINES = 0x02,
MNF_WITHXHTMLSPACE = 0x04,
MNF_WITHREFS = 0x08,
MNF_WITHNOEND = 0x10,
MNF_ESCAPEQUOTES = 0x100,
MNF_NONENDED = 0x100000,
MNF_ILLDATA = 0x200000,
};
enum MarkupNodeType
{
MNT_ELEMENT = 1, // 0x01
MNT_TEXT = 2, // 0x02
MNT_WHITESPACE = 4, // 0x04
MNT_CDATA_SECTION = 8, // 0x08
MNT_PROCESSING_INSTRUCTION = 16, // 0x10
MNT_COMMENT = 32, // 0x20
MNT_DOCUMENT_TYPE = 64, // 0x40
MNT_EXCLUDE_WHITESPACE = 123,// 0x7b
MNT_LONE_END_TAG = 128,// 0x80
MNT_NODE_ERROR = 32768 // 0x8000
};
bool GetOffsets( int& nStart, int& nEnd ) const;
// Create
bool Save( LPCTSTR szFileName );
const CString& GetDoc() const { return m_strDoc; };
bool AddElem( LPCTSTR szName, LPCTSTR szData=NULL, int nFlags=0 ) { return x_AddElem(szName,szData,nFlags); };
bool InsertElem( LPCTSTR szName, LPCTSTR szData=NULL, int nFlags=0 ) { return x_AddElem(szName,szData,nFlags|MNF_INSERT); };
bool AddChildElem( LPCTSTR szName, LPCTSTR szData=NULL, int nFlags=0 ) { return x_AddElem(szName,szData,nFlags|MNF_CHILD); };
bool InsertChildElem( LPCTSTR szName, LPCTSTR szData=NULL, int nFlags=0 ) { return x_AddElem(szName,szData,nFlags|MNF_INSERT|MNF_CHILD); };
bool AddElem( LPCTSTR szName, int nValue, int nFlags=0 ) { return x_AddElem(szName,nValue,nFlags); };
bool InsertElem( LPCTSTR szName, int nValue, int nFlags=0 ) { return x_AddElem(szName,nValue,nFlags|MNF_INSERT); };
bool AddChildElem( LPCTSTR szName, int nValue, int nFlags=0 ) { return x_AddElem(szName,nValue,nFlags|MNF_CHILD); };
bool InsertChildElem( LPCTSTR szName, int nValue, int nFlags=0 ) { return x_AddElem(szName,nValue,nFlags|MNF_INSERT|MNF_CHILD); };
bool AddAttrib( LPCTSTR szAttrib, LPCTSTR szValue ) { return x_SetAttrib(m_iPos,szAttrib,szValue); };
bool AddChildAttrib( LPCTSTR szAttrib, LPCTSTR szValue ) { return x_SetAttrib(m_iPosChild,szAttrib,szValue); };
bool AddAttrib( LPCTSTR szAttrib, int nValue ) { return x_SetAttrib(m_iPos,szAttrib,nValue); };
bool AddChildAttrib( LPCTSTR szAttrib, int nValue ) { return x_SetAttrib(m_iPosChild,szAttrib,nValue); };
bool AddSubDoc( LPCTSTR szSubDoc ) { return x_AddSubDoc(szSubDoc,0); };
bool InsertSubDoc( LPCTSTR szSubDoc ) { return x_AddSubDoc(szSubDoc,MNF_INSERT); };
CString GetSubDoc() const { return x_GetSubDoc(m_iPos); };
bool AddChildSubDoc( LPCTSTR szSubDoc ) { return x_AddSubDoc(szSubDoc,MNF_CHILD); };
bool InsertChildSubDoc( LPCTSTR szSubDoc ) { return x_AddSubDoc(szSubDoc,MNF_CHILD|MNF_INSERT); };
CString GetChildSubDoc() const { return x_GetSubDoc(m_iPosChild); };
bool AddNode( int nType, LPCTSTR szText ) { return x_AddNode(nType,szText,0); };
bool InsertNode( int nType, LPCTSTR szText ) { return x_AddNode(nType,szText,MNF_INSERT); };
// Modify
bool RemoveElem();
bool RemoveChildElem();
bool RemoveNode();
bool SetAttrib( LPCTSTR szAttrib, LPCTSTR szValue ) { return x_SetAttrib(m_iPos,szAttrib,szValue); };
bool SetChildAttrib( LPCTSTR szAttrib, LPCTSTR szValue ) { return x_SetAttrib(m_iPosChild,szAttrib,szValue); };
bool SetAttrib( LPCTSTR szAttrib, int nValue ) { return