在开发应用程序时,经常需要使用XML标记语言来存储和传输数据。然而,发现市面上用于辅助快速开始的示例应用程序非常少。平台SDK中的文档和示例似乎都是为Visual Basic/VBScript准备的,而不是为C++/MFC。
在这个示例应用程序中,尝试解析一个XML文件,并将其以基本的树状视图形式呈现。代码递归地遍历文档的元素和属性。一些已知的元素类型被赋予了标识图标,一些内容/值也被表达出来。
包含在.zip文件中的第一个XML文件包括一个DTD(文档类型定义)。
MSXML对象检测到的解析错误会在消息框中显示,并定位XML文档中的问题位置。
查看源代码中的解析器代码——它相当简单。
如果感兴趣,这个文件的长期目标是为应用程序提供可外部配置的toolbar和menu布局定义。由于客户的性质,最终用户定制还不适用,但所期望的规格很可能在离开项目后提出。
为了实现这个XML解析器,使用了C++和MFC(Microsoft Foundation Classes)。MFC是一个应用程序框架,它提供了一组可重用的类库,用于开发Windows应用程序。MSXML是Microsoft XML Parser的简称,它内置于Internet Explorer 4及以上版本中,使用的是IE5。
以下是实现XML解析器的一些关键步骤:
以下是解析XML文件并显示树状视图的示例代码片段:
#include <afxwin.h>
#include <msxml.h>
class CXMLParserApp : public CWinApp
{
public:
virtual BOOL InitInstance();
};
class CXMLParserDlg : public CDialog
{
// Construction
public:
CXMLParserDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CXMLParserDlg)
enum { IDD = IDD_XMLPARSER_DIALOG };
CTreeCtrl m_Tree;
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CXMLParserDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
//{{AFX_MSG(CXMLParserDlg)
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(CXMLParserDlg, CDialog)
//{{AFX_MSG_MAP(CXMLParserDlg)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
// CXMLParserApp
BOOL CXMLParserApp::InitInstance()
{
CWinApp::InitInstance();
CXMLParserDlg dlg;
m_pMainWnd = &dlg;
dlg.DoModal();
return FALSE;
}
// CXMLParserDlg message handlers
CXMLParserDlg::CXMLParserDlg(CWnd* pParent /*=NULL*/)
: CDialog(CXMLParserDlg::IDD, pParent)
{
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
}
void CXMLParserDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CXMLParserDlg)
DDX_Control(pDX, IDC_TREE, m_Tree);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CXMLParserDlg, CDialog)
//{{AFX_MSG_MAP(CXMLParserDlg)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
// CXMLParserDlg message handlers
BOOL CXMLParserDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
}
void CXMLParserDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
HCURSOR CXMLParserDlg::OnQueryDragIcon()
{
return static_cast(m_hIcon);
}
这段代码展示了如何创建一个MFC对话框应用程序,用于解析XML文件并显示树状视图。它使用了MSXML库来解析XML文件,并在对话框中显示解析结果。
在解析XML文件时,可能会遇到各种错误。MSXML对象提供了错误处理机制,可以在解析过程中捕获和处理这些错误。以下是处理解析错误的示例代码片段:
HRESULT hr = S_OK;
IXMLDOMParseError *pError = NULL;
try
{
// Load the XML document
hr = pXMLDoc->loadXML(bstrXML);
if (FAILED(hr))
{
// Display error message
MessageBox(NULL, _T("Failed to load XML document."), _T("Error"), MB_OK | MB_ICONERROR);
}
else
{
// Parse the XML document
hr = pXMLDoc->parseError(&pError);
if (SUCCEEDED(hr) && pError != NULL)
{
long line = 0;
long linepos = 0;
BSTR reason;
BSTR srcText;
pError->get_line(&line);
pError->get_linepos(&linepos);
pError->get_reason(&reason);
pError->get_srcText(&srcText);
CString errorStr;
errorStr.Format(_T("Error at line %d, column %d: %s\n%s"), line, linepos, reason, srcText);
MessageBox(NULL, errorStr, _T("XML Parse Error"), MB_OK | MB_ICONERROR);
}
}
}
catch (...)
{
MessageBox(NULL, _T("An unexpected error occurred."), _T("Error"), MB_OK | MB_ICONERROR);
}