MFC操作XML配置檔案的兩種方式:DOM 和 MSXML
這幾天做VC專案涉及到了建立xml配置檔案這方面的問題,糾結了好多天,嘗試了N種方法,終於完成了工作任務,現在和大家分享下:
我參考瞭如下的資料:
XML DOM 例項:http://www.w3school.com.cn/example/xdom_examples.asp
VC++中操作XML(MFC、SDK):http://www.cnblogs.com/lingyun1120/archive/2011/11/02/2232709.html
MFC 使用MsXML讀寫XML檔案:http://www.douban.com/note/150604463/
通過看這些資料發現使用DOM比使用MSXML程式碼要簡潔!但DOM網上的資料都不是很全!還是有許多小問題解決不了,所以綜合之下還是選用MSXML 做:
現在貼程式碼:
DataBind();//載入資料 MSXML2::IXMLDOMDocumentPtr pDoc;//生成xml檔案型別,定義名為pDoc MSXML2::IXMLDOMElementPtr xmlRoot;//生成第一個節點,定義名為xmlRoot //以下幾行用於檢驗xml檔案是否生成,照此格式寫就行了 HRESULT hr = pDoc.CreateInstance(__uuidof(MSXML2::DOMDocument30)); if(!SUCCEEDED(hr)) { MessageBox(_T("無法建立DOMDocument 物件,請檢查是否安裝了MSXMLParser 執行庫!")); } //建立並新增Xml 文件宣告 MSXML2::IXMLDOMProcessingInstructionPtr pXMLProc = NULL; pXMLProc = pDoc->createProcessingInstruction(_T("xml"),_T("version='1.0' encoding='UTF-8'")); _variant_t vNullVal; vNullVal.vt = VT_NULL; pDoc->insertBefore(pXMLProc, vNullVal); // 建立根結點 _variant_t varNodeType((short)MSXML2::NODE_ELEMENT); MSXML2::IXMLDOMNodePtr pXMLNodeRoot= NULL; pXMLNodeRoot = pDoc->createNode(varNodeType, _T("Root"), _T("")); // 新增根結點 pDoc->appendChild(pXMLNodeRoot); // 建立並新增下級結點 MSXML2::IXMLDOMNodePtr pXMLNodePatients= NULL; pXMLNodePatients = pXMLNodeRoot->appendChild(pDoc->createElement(_T("Patients")));
// 建立下級元素結點(PatientID)
MSXML2::IXMLDOMElementPtr pXMLElePatientID = NULL;
pXMLElePatientID = pDoc->createElement(_T("PatientID"));
pXMLElePatientID ->appendChild(pDoc->createTextNode((_bstr_t)strPatientID));
// 建立並設定下級結點屬性
MSXML2::IXMLDOMAttributePtr pXMLAttr = NULL;
pXMLAttr = pDoc->createAttribute(_T("ID"));
pXMLAttr->nodeTypedValue = "PatientID";
pXMLElePatientID->attributes->setNamedItem(pXMLAttr);
pXMLNodePatients->appendChild(pXMLElePatientID);
// 建立下級元素結點(Patient)
MSXML2::IXMLDOMElementPtr pXMLElePatient = NULL;
pXMLElePatient = pDoc->createElement(_T("Patient"));
pXMLElePatient->appendChild(pDoc->createTextNode((_bstr_t)strPatient));
pXMLAttr = pDoc->createAttribute(_T("ID"));
pXMLAttr->nodeTypedValue = "Patient";
pXMLElePatient->attributes->setNamedItem(pXMLAttr);
pXMLNodePatients->appendChild( pXMLElePatient);
//輸出XML資料檔案
CFileDialog hFileDlg(FALSE,NULL,NULL,OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST|OFN_READONLY,
TEXT("支援的XML檔案 (XML(*.xml)|*.XML||)"),NULL);
hFileDlg.m_ofn.nFilterIndex=1;
hFileDlg.m_ofn.hwndOwner=m_hWnd;
hFileDlg.m_ofn.lStructSize=sizeof(OPENFILENAME);
hFileDlg.m_ofn.lpstrTitle=TEXT("儲存XML資料檔案...\0");
hFileDlg.m_ofn.nMaxFile=MAX_PATH;
if(hFileDlg.DoModal() == IDOK)
{
strPath = hFileDlg.GetPathName();
pDoc->save((_bstr_t)strPath);//儲存檔案
isOpen=TRUE;
}
if (isOpen)
MessageBox(_T("資料檔案生成成功!位置:")+strPath);
else
MessageBox(_T("資料生成失敗!"));
pXMLNodeRoot.Release();
pDoc.Release();
使用DOM檢視節點
void CMenuSimulateOutPut::ProcessNode(CComPtr<IXMLDOMNode>& spNode) {
DOMNodeType eNodeType; spNode->get_nodeType(&eNodeType); if (eNodeType == NODE_ELEMENT) //只有NODE_ELEMENT型別才能包含有屬性和子節點 { BSTR bstrName,bstrText; //遞迴遍歷節點屬性 //向介面顯示相應欄位的內容 spNode->get_nodeName(&bstrName);
spNode->get_text(&bstrText);
ShowText(bstrName,bstrText);
CComPtr<IXMLDOMNamedNodeMap> spNameNodeMap; spNode->get_attributes(&spNameNodeMap);
long nLength; spNameNodeMap->get_length(&nLength); for (long i = 0; i != nLength; ++i) { CComPtr<IXMLDOMNode> spNodeAttrib; //注意屬性也是一個IXMLDOMNo
spNameNodeMap->get_item(i, &spNodeAttrib); ProcessNode(spNodeAttrib); }
//遞迴遍歷子節點 CComPtr<IXMLDOMNodeList> spNodeList; spNode->get_childNodes(&spNodeList); spNodeList->get_length(&nLength); for (long i=0;i!=nLength;i++) { CComPtr<IXMLDOMNode> spChildNode; spNodeList->get_item(i,&spChildNode); ProcessNode(spChildNode); } }
}
void CMenuSimulateOutPut::ShowNodes() { long i,nLen;
CComPtr<IXMLDOMElement>spRootEle; spDoc->get_documentElement(&spRootEle);//根節點
CComPtr<IXMLDOMNodeList>spNodeList; spRootEle->get_childNodes(&spNodeList);//子節點列表
spNodeList->get_length(&nLen);//子節點數 for (long i=0;i!=nLen;i++) { CComPtr<IXMLDOMNode>spNode; spNodeList->get_item(i,&spNode); ProcessNode(spNode);//節點處理函式
} }
void CMenuSimulateOutPut::ShowText(BSTR bstrName,BSTR bstrText) { if(_bstr_t("PatientID")==_bstr_t(bstrName)) { this->GetDlgItem(IDC_STATIC_PATIENTID)->SetWindowText(bstrText); } if(_bstr_t("Patient")==_bstr_t(bstrName)) { this->GetDlgItem(IDC_STATIC_PATIENT)->SetWindowText(bstrText); } if(_bstr_t("Sex")==_bstr_t(bstrName)) { this->GetDlgItem(IDC_STATIC_SEX)->SetWindowText(bstrText); } if(_bstr_t("Birth")==_bstr_t(bstrName)) { this->GetDlgItem(IDC_STATIC_BIRTH)->SetWindowText(bstrText); }
if(_bstr_t("FieldID")==_bstr_t(bstrName)) { this->GetDlgItem(IDC_STATIC_FIELDID)->SetWindowText(bstrText); } }
void CMenuSimulateOutPut::ShowNodes() { long i,nLen;
CComPtr<IXMLDOMElement>spRootEle; spDoc->get_documentElement(&spRootEle);//根節點
CComPtr<IXMLDOMNodeList>spNodeList; spRootEle->get_childNodes(&spNodeList);//子節點列表
spNodeList->get_length(&nLen);//子節點數 for (long i=0;i!=nLen;i++) { CComPtr<IXMLDOMNode>spNode; spNodeList->get_item(i,&spNode); ProcessNode(spNode);//節點處理函式
} }
void CMenuSimulateOutPut::OnBnClickedSimulateoutputOpen() { CString strFilters,strFileName; VARIANT_BOOL vb;
////讀取XML strFilters = _T("XML(*.xml)|*.XML||"); CFileDialog dlg(TRUE,_T("XML"),_T("1019GX.XML"),OFN_READONLY,strFilters, this);///TRUE為OPEN對話方塊,FALSE為SAVE AS對話方塊 if(dlg.DoModal()==IDOK){ FilePathName=dlg.GetPathName(); strFileName = FilePathName.AllocSysString(); spDoc.CoCreateInstance(CLSID_DOMDocument); spDoc->load(CComVariant(strFileName),&vb);//載入XML檔案 if (((bool)vb) == TRUE) // success! { FileIsOpen = true; AfxMessageBox(_T("XML檔案開啟成功!")); ShellExecute(this->m_hWnd,_T("open"),FilePathName,NULL,NULL,SW_SHOWNORMAL); ShowNodes(); } else { AfxMessageBox(_T("XML檔案打開出錯!")); return; } } }