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

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

大家好,欢迎来到IT知识分享网。

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之间的Text
	CString 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"
	//查询到一个或多个节点,返回第一个节点;如果没有查询的任何节点返回 Nothing
	pElemNode = (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);   //获取子结点个数  1
	for(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);  //初始化COM
	MSXML2::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);  //初始化COM
	m_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 == FALSE
		MessageBox("加载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")个数  2
	for(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
}

运行效果预览:

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

               实例下载链接,上传到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);  //初始化COM
	m_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 == FALSE
		MessageBox("加载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日

2017.04.25 更新

         主推C++语法实现的TinyXML。比起上面介绍的MSXML,TinyXML又简单又好用,而且接口文档/资料丰富。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/23991.html

(0)

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

关注微信