VC 使用msxml6.dll动态链接库中的函数读写XML文件

目录

1 引言

2 .dll使用方法

3 常用函数总结

4 实例应用

5 运行效果预览

6 补充说明

7 不足之处

8 更新

 

引言:

在C:\WINDOWS\system32\下有msxml3.dll 和 msxml6.dll两个动态链接库可以提供操作XML文件的函数。这两个只是版本不同,使用其一即可。

 

.dll使用方法:

#import "C:\\WINDOWS\\system32\\msxml6.dll"
        using namespace MSXML2;

 

常用函数总结:

  1. a.创建xml文档对象
  2. MSXML2::IXMLDOMDocumentPtr pDoc; //声明xml文档指针
  3. HRESULT hr = pDoc.CreateInstance(__uuidof(MSXML2::DOMDocument30));  //实例化xml文档对象
  4. delete pDoc;
  5. b.创建"Element"、添加"Element"到xml文档对象中
  6. MSXML2::IXMLDOMElementPtr xmlRoot;  //声明"Element"指针
  7. pDoc->raw_createElement( (_bstr_t)(char*)"China", &xmlRoot);  //创建"Element"
  8. pDoc->raw_appendChild(xmlRoot, NULL);  //添加"Element"到xml文档对象中
  9. c.为"Element"添加属性及其属性值
  10. MSXML2::IXMLDOMElementPtr pElemNode;
  11. pDoc->raw_createElement( (_bstr_t)(char*)"City", &childNode);
  12. pElemNode->setAttribute("population","7000");  //1:属性名  2:属性值
  13. d.元素之间的Text操作
  14. MSXML2::IXMLDOMElementPtr pElemNode;  //声明一个元素(Element)指针
  15. pElemNode->Puttext("shanghai");  //设置Element之间的Text
  16. CString strElemText = (char*)(_bstr_t)pElemNode->Gettext();  //获取Element之间的Text
  17. e.创建、保存XML文档
  18. pDoc->save(".\\test.xml");  //创建、保存并关闭xml文档
  19. f.加载xml文档
  20. MSXML2::IXMLDOMDocumentPtr pDoc;
  21. HRESULT loadrs = pDoc->load(".\\test.xml");  //加载xml文档
  22. g.查询"Element"
  23. //查询到一个或多个节点,返回第一个节点;如果没有查询的任何节点返回 Nothing
  24. pElemNode = (MSXML2::IXMLDOMElementPtr)(pDoc->selectSingleNode("//City"));  //获取元素的信息
  25. h.与xml一起常用的容器
  26. //IXMLDOMNamedNodeMap 是一个结点容器,允许通过name或index访问
  27. //这个容器是通常用于容纳属性
  28. MSXML2::IXMLDOMNamedNodeMapPtr pAttrs = NULL;
  29. //IXMLDOMNodeList 是一个动态容器,也就是说:添加、删除结点
  30. //以及改变结点,都会立即更新容器
  31. MSXML2::IXMLDOMNodeListPtr nodeList = NULL;
  32. //结点指针
  33. MSXML2::IXMLDOMNodePtr pAttrItem = NULL;
  34. j.容器的使用
  35. pElemNode->get_attributes(&pAttrs); //获取pElemNode指向的元素的属性集
  36. pElemNode->get_childNodes(&nodeList);  //获取子节点
  37. long nCount, iCount;
  38. //IXMLDOMNamedNodeMapPtr->get_length(long* )  返回容器中保存属性的个数
  39. pAttrs->get_length(&nCount);     //获取结点属性个数 2
  40. //IXMLDOMNodeListPtr->get_length(long* ) 返回容器中保存结点的个数
  41. nodeList->get_length(&iCount);   //获取子结点个数  1
  42. for(int i = 0; i < iCount; i++ ) //根据需要可以添加数据到ListControl中
  43. {
  44. CString strElemText = (char*)(_bstr_t)pElemNode->Gettext();  //获取Element标签之间的Text文本,Puttext(LPCSTR)为设置Text文本
  45. m_list.InsertItem(i,strElemText);  //1:行索引  2:待添加的字串
  46. for(int j = 0; j < nCount; j++ )
  47. {
  48. pAttrs->get_item(j,&pAttrItem);  //获取结点信息-结点
  49. //CString strAttrName = (char*)(_bstr_t)pAttrItem->nodeName;  //当前元素(Element)指定属性的名称
  50. CString strAttrVale = (char*)(_bstr_t)pAttrItem->nodeTypedValue;  //当前元素指定属性的值
  51. m_list.SetItemText(i,j+1,strAttrVale);  //1:行索引  2:列索引  3:待添加的字串
  52. //m_list.SetItemText(i,2,strAttrName);
  53. }
  54. }
  55. k.重要的函数
  56. <1>获取子元素
  57. IXMLDOMNodeListPtr nodelist=NULL;
  58. pElemNode->get_childNodes(&nodeList);   //两个函数是等效的
  59. nodelist = pElemNode->GetchildNodes();
  60. 保存pElementNode元素下的所有指向子元素的指针。
  61. <book category="children">
  62. <title lang="en">Harry Potter</title>
  63. <author>J K. Rowling</author>
  64. <year>2005</year>
  65. <price>29.99</price>
  66. </book>
  67. 如pElement指向 <book> </book>,则<title>、<author>、<year>、<price>都是pElement的子结点(或称为子元素)
  68. <2>返回nodeList容器中当前结点(应该是一个游标指针来实现的)的下一个结点。
  69. nodeList->nextNode()
  70. 例子:
  71. pElemNode = pDoc->selectSingleNode("//China");  //获取元素的信息
  72. MSXML2::IXMLDOMNodeListPtr nodeList = NULL;  //list容器
  73. pElemNode->get_childNodes(&nodeList);   //获取子节点
  74. pCurNode = nodeList->nextNode();
  75. <3>pCurNode->GetnextSibling()
  76. Retrieves the next sibling(元素处于同一树层级中) of this node in the parent's child list.如果无此节点,则返回 null。
  77. 备注:目前用法没有验证。
  78. 可配合下面两个函数使用:
  79. get_firstChild  Retrieves the first child of this node.
  80. get_lastChild   Retrieves the last child of this node.
  81. <4>获取元素的属性值
  82. <City population="12000" name="Wuhan"> </City>
  83. m_pCurNode指向<City> </City>这个元素
  84. CString varVal = m_pCurNode->getAttribute("population");  //varVal = "12000"
  1. ------特别注意--------
  2. <China>
  3. <City population="7000" area="2000">
  4. <Area> QingShan </Area>
  5. </City>
  6. </China>
  7. 如果pElemNode当前指向<City> </City>这个节点,
  8. 那么
  9. CString strElemText = (char*)(_bstr_t)pElemNode->Gettext();
  10. strElemText的值就是“QingShan”

实例应用

应用1:

  1. 测试用的xml文件-- test.xml
  2. <China>
  3. <City population="7000" area="2000">shanghai</City>
  4. <City population="39999" area="3322">beijing</City>
  5. <City population="5000" area="40000">Wuhan</City>
  6. </China>
  1. #import "C:\\WINDOWS\\system32\\msxml6.dll"
  2. using namespace MSXML2;
  3. //创建xml文件
  4. void COperateXMLDlg::OnBtnCreate()
  5. {
  6. // TODO: Add your control notification handler code here
  7. ::CoInitialize(NULL);  //初始化COM
  8. MSXML2::IXMLDOMDocumentPtr pDoc;
  9. MSXML2::IXMLDOMElementPtr xmlRoot;
  10. HRESULT hr = pDoc.CreateInstance(__uuidof(MSXML2::DOMDocument30));
  11. if(!SUCCEEDED(hr))
  12. {
  13. MessageBox("XML文件创建失败");
  14. return ;
  15. }
  16. pDoc->raw_createElement( (_bstr_t)(char*)"China", &xmlRoot);
  17. pDoc->raw_appendChild(xmlRoot, NULL);
  18. MSXML2::IXMLDOMElementPtr pElemNode;
  19. pDoc->raw_createElement( (_bstr_t)(char*)"City", &pElemNode);
  20. pElemNode->Puttext("shanghai");
  21. pElemNode->setAttribute("population","7000");
  22. pElemNode->setAttribute("area","2000");
  23. xmlRoot->appendChild(pElemNode);
  24. pDoc->raw_createElement( (_bstr_t)(char*)"City", &pElemNode);
  25. pElemNode->Puttext("beijing");
  26. pElemNode->setAttribute("population","39999");
  27. pElemNode->setAttribute("area","3322");
  28. xmlRoot->appendChild(pElemNode);
  29. pDoc->raw_createElement( (_bstr_t)(char*)"City", &pElemNode);
  30. pElemNode->Puttext("Wuhan");
  31. pElemNode->setAttribute("population","5000");
  32. pElemNode->setAttribute("area","40000");
  33. xmlRoot->appendChild(pElemNode);
  34. pDoc->save(".\\test.xml");
  35. //如何释放pDoc占有的内存
  36. ::CoUninitialize();  //卸载COM
  37. }
  38. //读取xml文件
  39. void COperateXMLDlg::OnBtnGetXML()
  40. {
  41. // TODO: Add your control notification handler code here
  42. ::CoInitialize(NULL);  //初始化COM
  43. m_list.DeleteAllItems();  //m_list是ListControl控件绑定的一个Value类型的变量
  44. MSXML2::IXMLDOMDocumentPtr pDoc;  //创建一个xml文档指针
  45. HRESULT hr = pDoc.CreateInstance(__uuidof(MSXML2::DOMDocument30));  //实例化文档指针
  46. if(!SUCCEEDED(hr))
  47. {
  48. MessageBox("加载XML错误");
  49. return ;
  50. }
  51. VARIANT_BOOL loadrs = pDoc->load(".\\test.xml");  //加载xml文档
  52. if( -1 != loadrs )  //查看load函数的定义(msxml3.tli)发现返回类型是VARIANT_BOOL,-1 == TRUE、0 == FALSE
  53. MessageBox("加载XML错误");
  54. MSXML2::IXMLDOMElementPtr pElemNode;  //声明一个元素(Element)指针
  55. // 在树中查找名为City的节点," // "表示在任意一层查找
  56. //selectSingleNode方法如果查询到一个或多个节点,返回第一个节点;如果没有查询的任何节点返回 Nothing
  57. //SelectNodes("//City")返回一个NodeList对象,可能包含多个节点
  58. pElemNode = (MSXML2::IXMLDOMElementPtr)(pDoc->selectSingleNode("//China"));  //获取元素的信息
  59. //MSXML2::DOMNodeType nodeType;  //结点类型
  60. //childNode->get_nodeType(&nodeType);
  61. //IXMLDOMNamedNodeMap 是一个结点容器,允许通过name或index访问
  62. //这个容器是通常用于容纳属性
  63. MSXML2::IXMLDOMNamedNodeMapPtr pAttrs = NULL;
  64. //IXMLDOMNodeList 是一个动态容器,也就是说:添加、删除结点
  65. //以及改变结点,都会立即更新容器
  66. MSXML2::IXMLDOMNodeListPtr nodeList = NULL;
  67. //结点指针
  68. MSXML2::IXMLDOMNodePtr pAttrItem = NULL;
  69. //pElemNode->get_attributes(&pAttrs); //获取pElemNode指向的元素的属性集
  70. pElemNode->get_childNodes(&nodeList);  //获取子节点
  71. long nCount, iCount;
  72. MSXML2::IXMLDOMElementPtr pCurNode;
  73. //IXMLDOMNamedNodeMapPtr->get_length(long* )  返回容器中保存属性的个数
  74. //pAttrs->get_length(&nCount);     //获取结点属性个数 2
  75. //IXMLDOMNodeListPtr->get_length(long* ) 返回容器中保存结点的个数
  76. nodeList->get_length(&iCount);   //获取子结点(此处指"China"元素下的子元素"City")个数  2
  77. for(int i = 0; i < iCount; i++ ) //根据需要可以添加数据到ListControl中
  78. {
  79. pCurNode = nodeList->nextNode();
  80. CString strPoupula = pCurNode->getAttribute("population");
  81. CString strArea= pCurNode->getAttribute("area");
  82. CString strElemText = (char*)(_bstr_t)pCurNode->Gettext();  //获取Element标签之间的Text文本,Puttext(LPCSTR)为设置Text文本
  83. m_list.InsertItem(i,strElemText);  //1:行索引  2:待添加的字串
  84. m_list.SetItemText(i,1,strPoupula); //1:行索引  2:列索引  3:待添加的字串
  85. m_list.SetItemText(i,2,strArea);
  86. }
  87. ::CoUninitialize();  //卸载COM
  88. }

运行效果预览:

VC 使用msxml6.dll动态链接库中的函数读写XML文件-LMLPHP

实例下载链接,上传到CSDN的资源库中,0分资源,支持VC6和VS2010IDE。下载此工程实例--VC6/VS2010

应用2:

  1. <China>
  2. <Provious name="Hubei">
  3. <City population="1" area="100">YiChang</City>
  4. <City population="2" area="40000">Wuhan</City>
  5. </Provious>
  6. <Provious name="HeBei">
  7. <City population="39999" area="3322">beijing</City>
  8. <City population="39999" area="3322">QingDao</City>
  9. </Provious>
  10. <Provious name="JiangSu">
  11. <City population="7000" area="2000">shanghai</City>
  12. </Provious>
  13. </China>
  1. void COperateXMLDlg::OnBtnGetXML()
  2. {
  3. // TODO: Add your control notification handler code here
  4. ::CoInitialize(NULL);  //初始化COM
  5. m_list.DeleteAllItems();
  6. MSXML2::IXMLDOMDocumentPtr pDoc;  //创建一个xml文档指针
  7. HRESULT hr = pDoc.CreateInstance(__uuidof(MSXML2::DOMDocument30));  //实例化文档指针
  8. if(!SUCCEEDED(hr))
  9. {
  10. MessageBox("加载XML错误");
  11. return ;
  12. }
  13. VARIANT_BOOL loadrs = pDoc->load(".\\test.xml");  //加载xml文档
  14. if( -1 != loadrs )  //查看load函数的定义(msxml3.tli)发现返回类型是VARIANT_BOOL,-1 == TRUE、0 == FALSE
  15. MessageBox("加载XML错误");
  16. MSXML2::IXMLDOMElementPtr pElemNode;  //声明一个元素(Element)指针
  17. // 在树中查找名为City的节点," // "表示在任意一层查找
  18. pElemNode = (MSXML2::IXMLDOMElementPtr)(pDoc->selectSingleNode("//China"));  //获取元素的信息
  19. MSXML2::IXMLDOMNamedNodeMapPtr pAttrs = NULL;
  20. MSXML2::IXMLDOMNodeListPtr nodeList = NULL;
  21. MSXML2::IXMLDOMNodePtr pAttrItem = NULL;
  22. pElemNode->get_childNodes(&nodeList);  //获取子节点
  23. long nCount, iCount,index=0;
  24. MSXML2::IXMLDOMElementPtr pCurNode,pChildCurNode;
  25. nodeList->get_length(&iCount);
  26. for(int i = 0; i < iCount; i++ ) //根据需要可以添加数据到ListControl中
  27. {
  28. pCurNode = nodeList->nextNode();
  29. MSXML2::IXMLDOMNodeListPtr ChildnodeList = NULL;
  30. pCurNode->get_childNodes(&ChildnodeList);
  31. ChildnodeList->get_length(&nCount);
  32. for(int j=0; j < nCount; j++ )
  33. {
  34. pChildCurNode = ChildnodeList->nextNode();
  35. CString strPoupula = pChildCurNode->getAttribute("population");
  36. CString strArea= pChildCurNode->getAttribute("area");
  37. CString strElemText = (char*)(_bstr_t)pChildCurNode->Gettext();  //获取Element标签之间的Text文本,Puttext(LPCSTR)为设置Text文本
  38. m_list.InsertItem(index,strElemText);  //1:行索引  2:待添加的字串
  39. m_list.SetItemText(index,1,strPoupula);
  40. m_list.SetItemText(index,2,strArea);
  41. index++;
  42. }
  43. }
  44. ::CoUninitialize();  //卸载COM
  45. }

补充说明:

项目中导入msxml3.dll或是msxml6.dll经过编译后会项目目录下生成两个文件msxml3.tlh和msxml3.tli(msxml6.tlh和msxml6.tli),绝大部分操作xml文件的函数都定义在msxml3.tli中,可在工程中选中函数名称右键查看其定义便会一目了然。

不足之处:

目前还没在Unicode字符集下成功的读取过,只要xml文件中包含Unicode字符,加载函数load("test.xml")就会返回加载失败的值。目前还没有找到原因。留此待已解决,Mark20131228.

问题解决了,在xml文件中少写了文件头“ <?xml version="1.0" encoding="gb2312"?> ”造成上面的load函数加载失败。Mark:20131231

更新:

20140311更 -- 解决每次写入信息到xml文件都是全覆盖模式,如此xml文件头<?xml version="1.0" encoding="gb2312"?>也会被覆盖掉,这样会引起“不足之处”里面提到的编码问题。找了很久没有找专门供写入xml文件头<?xml version="1.0" encoding="gb2312"?>的函数,于是自己动手写了一函数解决这个问题。

解决方法是:先将xml文件中原有的信息(此时不包括xml文件头)读取出来保存到一个字符串变量中,接着将<?xml version="1.0" encoding="gb2312"?>和字符串变量中的信息串接起来,然后再写入到xml文件中。代码如下

  1. BOOL AddXMLHeadString()
  2. {
  3. //由于必须从文件最开头添加字符会覆盖掉原来的字符,所以采用下面的方法解决这个问题
  4. //先把原始文件读取出来,然后加上xml的文件头字符串,再写回去。
  5. //char readBuf[]
  6. CString fileName(_T(".\\test.xml") );
  7. CStdioFile myfile;
  8. CFileException fileExcp;
  9. BOOL bRet = myfile.Open(fileName,CFile::typeText|CFile::modeReadWrite,&fileExcp);
  10. if( bRet )
  11. {
  12. /*一个稀奇事:如果1 、2 部分调换顺序就会使myfile.Read读取文件内容异常,但是两者的顺序是无关紧要的*/
  13. //1.读取原有文件的内容
  14. UINT fileLen = myfile.GetLength();
  15. char * readBuf = new char[fileLen];
  16. myfile.Read(readBuf,fileLen);
  17. //2.如果已经有了XML文件头就不添加
  18. CString strXMLHeader;
  19. myfile.ReadString(strXMLHeader);
  20. CString xmlHeader = _T("<?xml version=\"1.0\" encoding=\"gb2312\"?>");
  21. if(  xmlHeader== strXMLHeader )
  22. return TRUE;
  23. myfile.Close();
  24. //3.合成完整的xml文件
  25. CStdioFile newFile;
  26. BOOL bRetNewFile = newFile.Open(fileName,CFile::typeText|CFile::modeCreate|CFile::modeReadWrite,&fileExcp);
  27. if( bRetNewFile )
  28. {
  29. newFile.Seek(0,CFile::end);
  30. newFile.WriteString(_T("<?xml version=\"1.0\" encoding=\"gb2312\"?>\n"));
  31. newFile.Seek(0,CFile::end);
  32. newFile.Write(readBuf,fileLen);
  33. newFile.Seek(-1,CFile::end); //在文件末尾莫名其妙的多了一个‘?’,所以用了‘\n’将这个问号覆盖了,不然读取XML时会出错
  34. newFile.WriteString(_T("\n"));
  35. }
  36. }
  37. char *errinfo = new char [255];
  38. fileExcp.GetErrorMessage(errinfo,255);
  39. delete[] errinfo;
  40. return bRet;
  41. }

此更新工程下载连接。2014年3月11日

http://blog.csdn.net/qq2399431200/article/details/17583171

http://z.download.csdn.net/detail/qq2399431200/7022299

05-08 15:10