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

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

目录

1 引言

2 .dll使用方法

3 常用函数总结

4 实例应用

5 运行效果预览

6 补充说明

7 不足之处

8 更新

 

引言:

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

 

.dll使用方法:

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

 

常用函数总结:

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

[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  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>  



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

运行效果预览:

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

应用2:

[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  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>  
[cpp] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  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.   
  18.     // 在树中查找名为City的节点," // "表示在任意一层查找  
  19.     pElemNode = (MSXML2::IXMLDOMElementPtr)(pDoc->selectSingleNode("//China"));  //获取元素的信息  
  20.          
  21.         MSXML2::IXMLDOMNamedNodeMapPtr pAttrs = NULL;   
  22.     MSXML2::IXMLDOMNodeListPtr nodeList = NULL;  
  23.     MSXML2::IXMLDOMNodePtr pAttrItem = NULL;  
  24.   
  25.     pElemNode->get_childNodes(&nodeList);  //获取子节点  
  26.   
  27.     long nCount, iCount,index=0;  
  28.     MSXML2::IXMLDOMElementPtr pCurNode,pChildCurNode;  
  29.   
  30.     nodeList->get_length(&iCount);     
  31.     for(int i = 0; i < iCount; i++ ) //根据需要可以添加数据到ListControl中  
  32.     {  
  33.         pCurNode = nodeList->nextNode();  
  34.         MSXML2::IXMLDOMNodeListPtr ChildnodeList = NULL;  
  35.         pCurNode->get_childNodes(&ChildnodeList);  
  36.         ChildnodeList->get_length(&nCount);  
  37.         for(int j=0; j < nCount; j++ )  
  38.         {  
  39.             pChildCurNode = ChildnodeList->nextNode();  
  40.             CString strPoupula = pChildCurNode->getAttribute("population");  
  41.             CString strArea= pChildCurNode->getAttribute("area");  
  42.             CString strElemText = (char*)(_bstr_t)pChildCurNode->Gettext();  //获取Element标签之间的Text文本,Puttext(LPCSTR)为设置Text文本  
  43.           
  44.             m_list.InsertItem(index,strElemText);  //1:行索引  2:待添加的字串  
  45.             m_list.SetItemText(index,1,strPoupula);   
  46.             m_list.SetItemText(index,2,strArea);  
  47.             index++;  
  48.         }  
  49.     }  
  50.     ::CoUninitialize();  //卸载COM  
  51. }  



补充说明:

        项目中导入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文件中。代码如下

[cpp] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  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.           
  18.         //2.如果已经有了XML文件头就不添加  
  19.         CString strXMLHeader;  
  20.         myfile.ReadString(strXMLHeader);  
  21.         CString xmlHeader = _T("<?xml version="1.0" encoding="gb2312"?>");  
  22.         if(  xmlHeader== strXMLHeader )   
  23.             return TRUE;  
  24.   
  25.         myfile.Close();  
  26.   
  27.         //3.合成完整的xml文件  
  28.         CStdioFile newFile;  
  29.         BOOL bRetNewFile = newFile.Open(fileName,CFile::typeText|CFile::modeCreate|CFile::modeReadWrite,&fileExcp);  
  30.         if( bRetNewFile )  
  31.         {  
  32.             newFile.Seek(0,CFile::end);  
  33.             newFile.WriteString(_T("<?xml version="1.0" encoding="gb2312"?> "));  
  34.             newFile.Seek(0,CFile::end);  
  35.             newFile.Write(readBuf,fileLen);  
  36.             newFile.Seek(-1,CFile::end); //在文件末尾莫名其妙的多了一个‘?’,所以用了‘ ’将这个问号覆盖了,不然读取XML时会出错  
  37.             newFile.WriteString(_T(" "));  
  38.         }  
  39.     }  
  40.     char *errinfo = new char [255];  
  41.     fileExcp.GetErrorMessage(errinfo,255);  
  42.     delete[] errinfo;  
  43.   
  44.     return bRet;  
  45. }  

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

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

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

原文地址:https://www.cnblogs.com/findumars/p/6568652.html