在关于在MFC中使用TinyXML中介绍了为何研究在MFC中读取XML的原因。现在想来,如果是使用VC++.net,调用NETFramwwork中的XML处理库应该很简单吧。
1, 建立一个单文档应用程序,取名TestXML。备注,建立时ActiveX控件和数据库等等的支持全部不需要,但是,在选择CTestXMLView的基类的时候请选择CEditView
2, 在StdAfx.h中添加
#import "msxml3.dll" 这里最好是使用<>,这样的的话,使用""会产生C2782错误,
using namespace MSXML2;
第一句用于在程序的文件夹下生成MSXML3.TLH和MSXML3.TLI两个文件,第二句不是必须的,但最好添上,用于定义xml类时有时可以忽略MSXML2::。--注意,这个忽略不见得是好事,总之,为了避免命名冲突错误,以下的代码并没有忽略命名空间的引用
3, 在view类中添加LBUTTONDOWN命令响应:
首先在TestXMLView.h中添加下图以黄色标记的代码的代码:
然后在TestXMLView.cpp中的下图中添加黄色部分的代码
最后在TestXMLView.cpp添加如下的代码
void CTestXMLView::OnLButtonDown (UINT nFlags,CPoint point)
{
// BOOL变量m_bFirstDown用于区分第一次左击和以后的左击,第一次左击时仅需要从内存中创建一个
// XMLDocument对象,第二次以后的,需要通过文件系统从硬盘上装载相应的文件,将其装换成XMLDocument文档对象,
// 并将其赋值给pDoc对象指针
static BOOL m_bFirstDown =FALSE ;
// 计算单击的次数,注意局部的静态的变量,这个很重要的
static int count=0;
CString strCount,strNodeContent,xmlName =L"鼠标右击产生点数的记录.XML";
//备注:这所以使用命名空间限定的方法是因为,MSXML中msxml.dll使用的是MSXML命名空间--全局命名空间Msxml.h中
//msxml2,msxml3,msxml4等使用的MSXML2的命名空间,这两个命名空间中有一些相同的接口,会引起命名冲突
MSXML2::IXMLDOMDocumentPtr pDoc ; //定义名为pDoc的文件指针,指向生成的XML文件类,
MSXML2::IXMLDOMElementPtr xmlRoot ; //定义名为xmlRoot的XML元素类型的根节点的指针
MSXML2::IXMLDOMElementPtr childNode ; //childNode用于存储每次添加到XML文档中的字节点的元素
/*
* 函数原型:HRESULT CreateInstance(const CLSID& rclsid, IUnknown* pOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)
* 参数说明:CLSID 就是一种GUID,用来标示创建的文件的类型32位的数字
* 备注:该方法至少有三个重载,
*/
HRESULT hr = pDoc.CreateInstance(__uuidof(MSXML2::DOMDocument30));
if(!SUCCEEDED(hr))
{//SUCCEEDED宏是用来判断XML是否成功的生成的了文件,也可以使用FAILURED宏
MessageBox(L"无法创建DOMDocument对象,请检查是否安装了MSXML Parser运行库!");
}
if(!m_bFirstDown)
{
strCount.Format (_T("%d"),count);
xmlRoot=pDoc->createElement((_bstr_t)(char *)"Button");//创建一个命名为Button的根节点
pDoc->appendChild(xmlRoot);//把xmlRoot节点放到pDoc文档中下,成为pDoc文件的子节点,也就是以后所有新节点的根节点了
m_bFirstDown = TRUE;//第一次左击结束,准备第二次左击,更改标志
}
else
{
count ++; //记录单击的次数
strCount.Format (_T("%d"),count);
pDoc->load((_variant_t)xmlName); //将XML文档装载到文档对象中
pDoc->get_documentElement(&xmlRoot); //获取根节点,函数执行完后xmlRoot是根节点
}
strNodeContent.Format(_T("Point.x=%d,Point.y=%d"),point.x,point.y);//记录左击坐标
/*
* 函数原型申明:MSXML2::IXMLDOMElementPtr MSXML2::IXMLDOMDocument::createElement(_bstr_t tagName)
* _bstr_t 以及下面出现的_variant_t都是为了COM的互操作性提供类型转换的工具类
* 考虑各种语言度可以和COM进行通信和调用COM提供的服务,类型的转化必然是不可避免的问题
*/
childNode=pDoc->createElement((_bstr_t)(char *)"Point");//注意类型装换的格式
childNode->put_text((_bstr_t)strNodeContent); //向子节点中添加相应的内容
childNode->setAttribute(L"ID",(_variant_t)strCount);//设置字节点的属性,注意strCount要转化类型
xmlRoot->appendChild(childNode); //将字节点挂载到父节点上
pDoc->save((_variant_t)xmlName); //将内存中的XML文档对象保存到硬盘中
childNode.Release();
xmlRoot.Release();
pDoc.Release();//释放相应的内存资源,注意释放的次序,不可以颠倒这个次序
CView::OnLButtonDown(nFlags, point); //调用父类的处理鼠标右击的事件
}
4, 生成的xml文件如下所示
需要注意一下的是,在vs2010d调试的时候,这个XML文件在工程文件下产生
而在Debug文件夹下直接运行程序的时候,这个文件就在当前的文件夹下产生:
以上的代码仅仅能够创建并添加XML文档类型的节点
XML的其他例子参考:http://wenku.baidu.com/view/3d6403d8d15abe23482f4de0.html 不过其中的程序在VC6.0上编译可以运行,但是在vs2010中是不能运行的,运行的过程中出现过这样的几个错误:C2872(注意是应为命名空间的问题,同名函数冲突污染的问题),C2660(函数参数不匹配的问题),C2664(函数参数隐式装换不成功的问题)关于这其中的一些错误的说明:参考:http://support.microsoft.com/default.aspx?scid=kb;en-us;316317&wa=wsignin1.0
这里有这么几个原因:
1,微软将COM中的函数的接口改了,比如说以前是通过指针的获取响应的值的现在是通过返回值来获取的
2.一些函数与之前的有所不同了,比如说raw_createElement(),现在的命名名称是createElement(),就是这个函数体现了第一个原因:以前可能是像这样的调用的形式:
pDoc->raw_createElement((_bstr_t)(char *)"Point",&childNode);
现在的形式是:childNode=pDoc->createElement((_bstr_t)(char *)"Point");
这里测试实例的程序的原代码的地址:http://pan.baidu.com/share/link?shareid=156828&uk=556148328
再次看到自己之前的写得博客,惨不忍睹,我都不知道我当时是怎么写出这样的博客的,前后不通,逻辑混乱。虽然,现在自己的写的也不怎么地,不过,这也算是自己成长了吧,成长总是要不断的肯定否定的,谁不能直接吃第8个烧饼就饱了。
关于TinyXML,有机会的话在Ubuntu下使用一下,再来修改这篇文章吧。
1.学习XML的两个小程序:http://wenku.baidu.com/view/3d6403d8d15abe23482f4de0.html
2.Virual studio的错误:http://support.microsoft.com/default.aspx?scid=kb;en-us;316317&wa=wsignin1.0