XML文件读写
这里是利用COM组建对xml文件进行操作,所以程序进入时要进行COM组件的初始化和卸载
::CoInitialize(NULL); 和 ::CoUninitialize();要对应
为了不影响其他地方的操作,最好把这个放在项目的开始和结束
你也可以使用AfxOleInit();他对CoInitialize进行了封装,具体的区别可以到网上查一下
另外确保安装了MS XML Parser 运行库
使用时需要加上
#import <msxml3.dll>
下面的两个函数就是对xml文件的操作,大部分操作都已涉及
/////////////////////////////////////////////////////////////////////////////// #import <msxml3.dll> typedef MSXML2::IXMLDOMDocumentPtr DOMDocumentPtr; typedef MSXML2::IXMLDOMElementPtr DOMElementPtr; typedef MSXML2::IXMLDOMProcessingInstructionPtr DOMProInstructionPtr; typedef MSXML2::IXMLDOMNamedNodeMapPtr DOMNamedNodeMapPtr; typedef MSXML2::IXMLDOMNodeListPtr DOMNodeListPtr; typedef MSXML2::IXMLDOMNodePtr DOMNodePtr; typedef MSXML2::IXMLDOMTextPtr DOMTextPtr; /////////////////////////////////////////////////////////////////////////////// int ReadXML(CString szXMLFile) { if (szXMLFile.IsEmpty()) return -1; DOMDocumentPtr pXMLDoc; CString szText; // 初始化COM组件,必须与::CoUninitialize();相对应 // 这里可以这么使用,但以后尽量在程序开始调用,程序结束卸载,否则可能会影响到其他地方使用 // 用AfxOleInit();也可以,但也必须确保只调用了一次,最好放在程序的开始 ::CoInitialize(NULL); // 创建DOMDocument对象,并判断是否创建成功 HRESULT hr = pXMLDoc.CreateInstance(__uuidof(MSXML2::DOMDocument30)); if(!SUCCEEDED(hr)) { MessageBox(NULL, "无法创建DOMDocument对象,请检查是否安装了MS XML Parser 运行库!", "Error", MB_ICONERROR|MB_OK); return -1; } if(pXMLDoc->load(_variant_t(szXMLFile)) == FALSE) { MessageBox(NULL, "无法打开存档!", "Error", MB_ICONERROR|MB_OK); return -2; } // 是否有根节点,取得根节点 DOMElementPtr pRootElem = pXMLDoc->GetdocumentElement(); if (pRootElem == NULL) return -3; // 取得根节点的名字 szText = (char*)(pRootElem->GetnodeName()); // 在根节点下查找名叫Globals的节点并取得 DOMNodePtr pGlobalNode = pRootElem->selectSingleNode("Globals"); if (pGlobalNode == NULL) return -3; // 取得属性列表 DOMNamedNodeMapPtr pNodeMap = pGlobalNode->Getattributes(); // 根据名字直接取得属性节点并获取值 DOMNodePtr pAttribNode = pNodeMap->getNamedItem("Attrib"); szText = (char *)(pAttribNode->Gettext()); pAttribNode = pNodeMap->getNamedItem("作用"); szText = (char *)(pAttribNode->Gettext()); // 另外在有些情况下Node可以转换成Element使用 DOMElementPtr pGlobalElem = pGlobalNode; szText = (char*)(_bstr_t)(pGlobalElem->getAttribute("Attrib")); szText = (char*)(_bstr_t)(pGlobalElem->getAttribute("作用")); // 如果不知道名字可以取得属性的个数,逐个查找属性 long len = pNodeMap->Getlength(); for (int i=0; i<len; ++i) { pAttribNode = pNodeMap->Getitem(i); szText = (char *)(pAttribNode->GetnodeName()); // 取得属性名字 szText = (char *)(pAttribNode->Gettext()); // 取得属性值 } DOMNodePtr pTempNode; // 取得Globals下的子节点 if((pTempNode = pGlobalNode->GetfirstChild())) { szText = (char*)pTempNode->GetnodeName(); szText = (char*)pTempNode->Gettext(); // 循环取得相邻的节点 while((pTempNode = pTempNode->GetnextSibling())) { szText = (char*)pTempNode->GetnodeName(); szText = (char*)pTempNode->Gettext(); } } // 从根节点中查找Data的子节点 DOMNodePtr pDataNode = pRootElem->selectSingleNode("Data"); if (pDataNode == NULL) return -1; // 从Data节点下列取出所有叫Data的节点 DOMNodeListPtr pDataList = pDataNode->selectNodes("Data"); len = pDataList->Getlength(); for(i=0; i<len; ++i) { pTempNode = pDataList->Getitem(i); szText = (char*)pTempNode->GetnodeName(); szText = (char*)pTempNode->Gettext(); } // 确保卸载掉所有的对象才能调用CoUninitialize if(pNodeMap)pNodeMap.Detach(); if(pAttribNode)pAttribNode.Detach(); if(pTempNode)pTempNode.Detach(); if(pGlobalNode)pGlobalNode.Detach(); if(pGlobalElem)pGlobalElem.Detach(); if(pDataNode)pDataNode.Detach(); if(pDataList)pDataList.Detach(); if(pRootElem)pRootElem.Detach(); if(pXMLDoc)pXMLDoc.Detach(); // 卸掉COM,必须与CoInitialize对应 ::CoUninitialize(); return 0; } int SaveXML(CString szXMLFile) { DOMDocumentPtr pXMLDoc; CString szText; // 初始化COM组件,必须与::CoUninitialize();相对应 // 这里可以这么使用,但以后尽量在程序开始调用,程序结束卸载,否则可能会影响到其他地方使用 // 用AfxOleInit();也可以,但也必须确保只调用了一次,最好放在程序的开始 ::CoInitialize(NULL); // 创建DOMDocument对象,并判断是否创建成功 HRESULT hr = pXMLDoc.CreateInstance(__uuidof(MSXML2::DOMDocument30)); if(!SUCCEEDED(hr)) { MessageBox(NULL, "无法创建DOMDocument对象,请检查是否安装了MS XML Parser 运行库!", "Error", MB_ICONERROR|MB_OK); return -1; } // 创建头节点 DOMProInstructionPtr pXmlProNode = pXMLDoc->createProcessingInstruction(_bstr_t("xml"),_bstr_t("version=\"1.0\" encoding = \"GB2312\"")); pXMLDoc->appendChild((MSXML2::IXMLDOMNodePtr)pXmlProNode); pXmlProNode.Detach(); //以后不再用的,卸掉 // 创建并添加根节点 // 创建一个节点 DOMElementPtr pXmlRoot = pXMLDoc->createElement("root"); // 添加到文档中 pXMLDoc->appendChild(pXmlRoot); // 创建一个节点 DOMElementPtr pGlobalNode = pXMLDoc->createElement("Globals"); // 添加到根节点中 pXmlRoot->appendChild(pGlobalNode); // 添加两个属性 pGlobalNode->setAttribute("Attrib", "Value"); pGlobalNode->setAttribute("作用", "记录全局数据"); DOMElementPtr pTempNode = pXMLDoc->createElement("Author"); pTempNode->Puttext("Ren.Xia");// 添加内容 pGlobalNode->appendChild(pTempNode); pTempNode.Detach(); pTempNode = pXMLDoc->createElement("Date"); pTempNode->Puttext("2011-02-12");// 添加内容 pGlobalNode->appendChild(pTempNode); pTempNode.Detach(); pGlobalNode.Detach(); // 在Root下创建Data子节点 DOMElementPtr pDataNode = pXMLDoc->createElement("Data"); pDataNode->setAttribute("Attrib", "Value"); pDataNode->setAttribute("作用", "记录数据"); pXmlRoot->appendChild(pDataNode); for (int i=0; i<100; ++i) { pTempNode = pXMLDoc->createElement("Data"); szText.Format("%d", i); pTempNode->Puttext((_bstr_t)szText); pDataNode->appendChild(pTempNode); pTempNode.Detach(); } pDataNode.Detach(); // 判断名字是否为空 if (szXMLFile.IsEmpty()) { pXmlRoot.Detach(); pXMLDoc.Detach(); return -2; } // 存储并判断是否成功 hr = pXMLDoc->save((LPCTSTR)szXMLFile); pXmlRoot.Detach(); pXMLDoc.Detach(); if(!SUCCEEDED(hr)) { MessageBox(NULL, "无法保存!", "Error", MB_ICONERROR|MB_OK); return -3; } MessageBox(NULL, "保存完毕!", "Error", MB_ICONASTERISK|MB_OK); // 卸掉COM,必须与CoInitialize对应 ::CoUninitialize(); return 0; }
另外如果知道一个节点的名字"Data",但是不知道在哪一层,那个树下
可以在查找时名字前加个"//"这样就表示在任意一层查找
pRootElem->selectSingleNode(" //Data");
-
本文附件下载:
- XML.rar (484.4 KB)