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

来源:互联网 发布:增广贤文 知乎 编辑:程序博客网 时间:2024/04/29 16:22

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;


常用函数总结:

 

a.创建xml文档对象MSXML2::IXMLDOMDocumentPtr pDoc; //声明xml文档指针HRESULT hr = pDoc.CreateInstance(__uuidof(MSXML2::DOMDocument30));  //实例化xml文档对象delete pDoc;  b.创建"Element"、添加"Element"到xml文档对象中MSXML2::IXMLDOMElementPtr xmlRoot;  //声明"Element"指针pDoc->raw_createElement( (_bstr_t)(char*)"China", &xmlRoot);  //创建"Element"pDoc->raw_appendChild(xmlRoot, NULL);  //添加"Element"到xml文档对象中c.为"Element"添加属性及其属性值    MSXML2::IXMLDOMElementPtr pElemNode;pDoc->raw_createElement( (_bstr_t)(char*)"City", &childNode);pElemNode->setAttribute("population","7000");  //1:属性名  2:属性值d.元素之间的Text操作MSXML2::IXMLDOMElementPtr pElemNode;  //声明一个元素(Element)指针pElemNode->Puttext("shanghai");  //设置Element之间的TextCString strElemText = (char*)(_bstr_t)pElemNode->Gettext();  //获取Element之间的Text         e.创建、保存XML文档pDoc->save(".\\test.xml");  //创建、保存并关闭xml文档f.加载xml文档MSXML2::IXMLDOMDocumentPtr pDoc;HRESULT loadrs = pDoc->load(".\\test.xml");  //加载xml文档g.查询"Element"//查询到一个或多个节点,返回第一个节点;如果没有查询的任何节点返回 NothingpElemNode = (MSXML2::IXMLDOMElementPtr)(pDoc->selectSingleNode("//City"));  //获取元素的信息h.与xml一起常用的容器    //IXMLDOMNamedNodeMap 是一个结点容器,允许通过name或index访问   //这个容器是通常用于容纳属性    MSXML2::IXMLDOMNamedNodeMapPtr pAttrs = NULL;//IXMLDOMNodeList 是一个动态容器,也就是说:添加、删除结点  //以及改变结点,都会立即更新容器     MSXML2::IXMLDOMNodeListPtr nodeList = NULL;//结点指针MSXML2::IXMLDOMNodePtr pAttrItem = NULL;j.容器的使用    pElemNode->get_attributes(&pAttrs); //获取pElemNode指向的元素的属性集pElemNode->get_childNodes(&nodeList);  //获取子节点long nCount, iCount;//IXMLDOMNamedNodeMapPtr->get_length(long* )  返回容器中保存属性的个数pAttrs->get_length(&nCount);     //获取结点属性个数 2//IXMLDOMNodeListPtr->get_length(long* ) 返回容器中保存结点的个数nodeList->get_length(&iCount);   //获取子结点个数  1for(int i = 0; i < iCount; i++ ) //根据需要可以添加数据到ListControl中{CString strElemText = (char*)(_bstr_t)pElemNode->Gettext();  //获取Element标签之间的Text文本,Puttext(LPCSTR)为设置Text文本m_list.InsertItem(i,strElemText);  //1:行索引  2:待添加的字串for(int j = 0; j < nCount; j++ ){pAttrs->get_item(j,&pAttrItem);  //获取结点信息-结点//CString strAttrName = (char*)(_bstr_t)pAttrItem->nodeName;  //当前元素(Element)指定属性的名称CString strAttrVale = (char*)(_bstr_t)pAttrItem->nodeTypedValue;  //当前元素指定属性的值m_list.SetItemText(i,j+1,strAttrVale);  //1:行索引  2:列索引  3:待添加的字串//m_list.SetItemText(i,2,strAttrName); }}k.重要的函数  <1>获取子元素     IXMLDOMNodeListPtr nodelist=NULL;     pElemNode->get_childNodes(&nodeList);   //两个函数是等效的     nodelist = pElemNode->GetchildNodes();     保存pElementNode元素下的所有指向子元素的指针。<book category="children"><title lang="en">Harry Potter</title><author>J K. Rowling</author><year>2005</year><price>29.99</price></book> 如pElement指向 <book> </book>,则<title>、<author>、<year>、<price>都是pElement的子结点(或称为子元素)    <2>返回nodeList容器中当前结点(应该是一个游标指针来实现的)的下一个结点。     nodeList->nextNode()     例子:     pElemNode = pDoc->selectSingleNode("//China");  //获取元素的信息 MSXML2::IXMLDOMNodeListPtr nodeList = NULL;  //list容器     pElemNode->get_childNodes(&nodeList);   //获取子节点 pCurNode = nodeList->nextNode();  <3>pCurNode->GetnextSibling()     Retrieves the next sibling(元素处于同一树层级中) of this node in the parent's child list.如果无此节点,则返回 null。 备注:目前用法没有验证。 可配合下面两个函数使用: get_firstChild  Retrieves the first child of this node. get_lastChild   Retrieves the last child of this node.     <4>获取元素的属性值     <City population="12000" name="Wuhan"> </City>     m_pCurNode指向<City> </City>这个元素     CString varVal = m_pCurNode->getAttribute("population");  //varVal = "12000"


 ------特别注意--------           <China>               <City population="7000" area="2000">                  <Area> QingShan </Area>               </City>             </China>         如果pElemNode当前指向<City> </City>这个节点,        那么                     CString strElemText = (char*)(_bstr_t)pElemNode->Gettext();         strElemText的值就是“QingShan”


实例应用

应用1:

测试用的xml文件-- test.xml<China>    <City population="7000" area="2000">shanghai</City><City population="39999" area="3322">beijing</City>    <City population="5000" area="40000">Wuhan</City></China>


#import "C:\\WINDOWS\\system32\\msxml6.dll" using namespace MSXML2;//创建xml文件 void COperateXMLDlg::OnBtnCreate() {// TODO: Add your control notification handler code here::CoInitialize(NULL);  //初始化COMMSXML2::IXMLDOMDocumentPtr pDoc;MSXML2::IXMLDOMElementPtr xmlRoot;HRESULT hr = pDoc.CreateInstance(__uuidof(MSXML2::DOMDocument30));if(!SUCCEEDED(hr)){MessageBox("XML文件创建失败");return ;}pDoc->raw_createElement( (_bstr_t)(char*)"China", &xmlRoot);pDoc->raw_appendChild(xmlRoot, NULL);MSXML2::IXMLDOMElementPtr pElemNode;pDoc->raw_createElement( (_bstr_t)(char*)"City", &pElemNode);pElemNode->Puttext("shanghai");pElemNode->setAttribute("population","7000");pElemNode->setAttribute("area","2000");xmlRoot->appendChild(pElemNode);pDoc->raw_createElement( (_bstr_t)(char*)"City", &pElemNode);pElemNode->Puttext("beijing");pElemNode->setAttribute("population","39999");pElemNode->setAttribute("area","3322");xmlRoot->appendChild(pElemNode);pDoc->raw_createElement( (_bstr_t)(char*)"City", &pElemNode);pElemNode->Puttext("Wuhan");pElemNode->setAttribute("population","5000");pElemNode->setAttribute("area","40000");xmlRoot->appendChild(pElemNode);pDoc->save(".\\test.xml");//如何释放pDoc占有的内存::CoUninitialize();  //卸载COM}//读取xml文件void COperateXMLDlg::OnBtnGetXML() {// TODO: Add your control notification handler code here::CoInitialize(NULL);  //初始化COMm_list.DeleteAllItems();  //m_list是ListControl控件绑定的一个Value类型的变量MSXML2::IXMLDOMDocumentPtr pDoc;  //创建一个xml文档指针HRESULT hr = pDoc.CreateInstance(__uuidof(MSXML2::DOMDocument30));  //实例化文档指针if(!SUCCEEDED(hr)){MessageBox("加载XML错误");return ;}VARIANT_BOOL loadrs = pDoc->load(".\\test.xml");  //加载xml文档if( -1 != loadrs )  //查看load函数的定义(msxml3.tli)发现返回类型是VARIANT_BOOL,-1 == TRUE、0 == FALSEMessageBox("加载XML错误");MSXML2::IXMLDOMElementPtr pElemNode;  //声明一个元素(Element)指针// 在树中查找名为City的节点," // "表示在任意一层查找//selectSingleNode方法如果查询到一个或多个节点,返回第一个节点;如果没有查询的任何节点返回 Nothing//SelectNodes("//City")返回一个NodeList对象,可能包含多个节点pElemNode = (MSXML2::IXMLDOMElementPtr)(pDoc->selectSingleNode("//China"));  //获取元素的信息//MSXML2::DOMNodeType nodeType;  //结点类型//childNode->get_nodeType(&nodeType);//IXMLDOMNamedNodeMap 是一个结点容器,允许通过name或index访问   //这个容器是通常用于容纳属性    MSXML2::IXMLDOMNamedNodeMapPtr pAttrs = NULL;//IXMLDOMNodeList 是一个动态容器,也就是说:添加、删除结点  //以及改变结点,都会立即更新容器     MSXML2::IXMLDOMNodeListPtr nodeList = NULL;//结点指针MSXML2::IXMLDOMNodePtr pAttrItem = NULL;//pElemNode->get_attributes(&pAttrs); //获取pElemNode指向的元素的属性集pElemNode->get_childNodes(&nodeList);  //获取子节点long nCount, iCount;MSXML2::IXMLDOMElementPtr pCurNode;//IXMLDOMNamedNodeMapPtr->get_length(long* )  返回容器中保存属性的个数//pAttrs->get_length(&nCount);     //获取结点属性个数 2//IXMLDOMNodeListPtr->get_length(long* ) 返回容器中保存结点的个数nodeList->get_length(&iCount);   //获取子结点(此处指"China"元素下的子元素"City")个数  2for(int i = 0; i < iCount; i++ ) //根据需要可以添加数据到ListControl中{pCurNode = nodeList->nextNode();CString strPoupula = pCurNode->getAttribute("population");CString strArea= pCurNode->getAttribute("area");CString strElemText = (char*)(_bstr_t)pCurNode->Gettext();  //获取Element标签之间的Text文本,Puttext(LPCSTR)为设置Text文本m_list.InsertItem(i,strElemText);  //1:行索引  2:待添加的字串m_list.SetItemText(i,1,strPoupula); //1:行索引  2:列索引  3:待添加的字串m_list.SetItemText(i,2,strArea);}::CoUninitialize();  //卸载COM}

运行效果预览:

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


应用2:

<China>    <Provious name="Hubei"><City population="1" area="100">YiChang</City><City population="2" area="40000">Wuhan</City></Provious><Provious name="HeBei"><City population="39999" area="3322">beijing</City><City population="39999" area="3322">QingDao</City></Provious><Provious name="JiangSu"><City population="7000" area="2000">shanghai</City></Provious></China>

void COperateXMLDlg::OnBtnGetXML() {// TODO: Add your control notification handler code here::CoInitialize(NULL);  //初始化COMm_list.DeleteAllItems();MSXML2::IXMLDOMDocumentPtr pDoc;  //创建一个xml文档指针HRESULT hr = pDoc.CreateInstance(__uuidof(MSXML2::DOMDocument30));  //实例化文档指针if(!SUCCEEDED(hr)){MessageBox("加载XML错误");return ;}VARIANT_BOOL loadrs = pDoc->load(".\\test.xml");  //加载xml文档if( -1 != loadrs )  //查看load函数的定义(msxml3.tli)发现返回类型是VARIANT_BOOL,-1 == TRUE、0 == FALSEMessageBox("加载XML错误");MSXML2::IXMLDOMElementPtr pElemNode;  //声明一个元素(Element)指针// 在树中查找名为City的节点," // "表示在任意一层查找pElemNode = (MSXML2::IXMLDOMElementPtr)(pDoc->selectSingleNode("//China"));  //获取元素的信息               MSXML2::IXMLDOMNamedNodeMapPtr pAttrs = NULL; MSXML2::IXMLDOMNodeListPtr nodeList = NULL;MSXML2::IXMLDOMNodePtr pAttrItem = NULL;pElemNode->get_childNodes(&nodeList);  //获取子节点long nCount, iCount,index=0;MSXML2::IXMLDOMElementPtr pCurNode,pChildCurNode;nodeList->get_length(&iCount);   for(int i = 0; i < iCount; i++ ) //根据需要可以添加数据到ListControl中{pCurNode = nodeList->nextNode();MSXML2::IXMLDOMNodeListPtr ChildnodeList = NULL;pCurNode->get_childNodes(&ChildnodeList);ChildnodeList->get_length(&nCount);for(int j=0; j < nCount; j++ ){pChildCurNode = ChildnodeList->nextNode();CString strPoupula = pChildCurNode->getAttribute("population");CString strArea= pChildCurNode->getAttribute("area");CString strElemText = (char*)(_bstr_t)pChildCurNode->Gettext();  //获取Element标签之间的Text文本,Puttext(LPCSTR)为设置Text文本m_list.InsertItem(index,strElemText);  //1:行索引  2:待添加的字串m_list.SetItemText(index,1,strPoupula); m_list.SetItemText(index,2,strArea);index++;}}::CoUninitialize();  //卸载COM}



补充说明:

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

BOOL AddXMLHeadString(){//由于必须从文件最开头添加字符会覆盖掉原来的字符,所以采用下面的方法解决这个问题//先把原始文件读取出来,然后加上xml的文件头字符串,再写回去。//char readBuf[]CString fileName(_T(".\\test.xml") );CStdioFile myfile;CFileException fileExcp;BOOL bRet = myfile.Open(fileName,CFile::typeText|CFile::modeReadWrite,&fileExcp);if( bRet ){   /*一个稀奇事:如果1 、2 部分调换顺序就会使myfile.Read读取文件内容异常,但是两者的顺序是无关紧要的*///1.读取原有文件的内容UINT fileLen = myfile.GetLength();char * readBuf = new char[fileLen];myfile.Read(readBuf,fileLen);//2.如果已经有了XML文件头就不添加CString strXMLHeader;myfile.ReadString(strXMLHeader);CString xmlHeader = _T("<?xml version=\"1.0\" encoding=\"gb2312\"?>");if(  xmlHeader== strXMLHeader ) return TRUE;myfile.Close();//3.合成完整的xml文件CStdioFile newFile;BOOL bRetNewFile = newFile.Open(fileName,CFile::typeText|CFile::modeCreate|CFile::modeReadWrite,&fileExcp);if( bRetNewFile ){newFile.Seek(0,CFile::end);newFile.WriteString(_T("<?xml version=\"1.0\" encoding=\"gb2312\"?>\n"));newFile.Seek(0,CFile::end);newFile.Write(readBuf,fileLen);newFile.Seek(-1,CFile::end); //在文件末尾莫名其妙的多了一个‘?’,所以用了‘\n’将这个问号覆盖了,不然读取XML时会出错newFile.WriteString(_T("\n"));}}char *errinfo = new char [255];fileExcp.GetErrorMessage(errinfo,255);delete[] errinfo;return bRet;}
                  此更新工程下载连接。2014年3月11日






4 0
原创粉丝点击