VC++中操作XML(MFC、SDK)
- 格式:doc
- 大小:45.50 KB
- 文档页数:5
C++中的XML和JSON处理在C++中,XML和JSON是两种常用的数据格式,可以用来存储和传输结构化数据。
XML(可扩展标记语言)是一种标记语言,而JSON (JavaScript对象表示)是一种数据交换格式。
它们都具有易读、易解析的特性,被广泛应用于网络通信、配置文件、数据存储等方面。
首先我们来看一下XML在C++中的处理。
C++有一些开源的XML库可以用来解析和生成XML数据,其中较为常用的有Xerces-C++、TinyXML、RapidXML等。
这些库提供了丰富的API和功能,可以方便地读取、修改和生成XML文档。
Xerces-C++是一个功能强大的XML解析库,支持DOM(文档对象模型)和SAX(简单API for XML)两种解析方式。
DOM方式以树状结构表示XML文档,允许很方便地遍历和修改XML数据;而SAX方式则是一种事件驱动的解析方式,逐行解析XML文档,适用于大型XML文档的处理。
Xerces-C++还提供了一些辅助函数用于生成XML文档,并且支持XPath等高级查询语言。
TinyXML是一个轻量级的XML解析库,简单易用。
它使用C++的对象模型来表示XML文档,可以方便地读取和修改XML数据。
TinyXML没有SAX解析方式,但提供了较为简单的DOM接口,适用于小型XML文档的处理。
TinyXML还支持XPath查询,方便地对XML文档进行高级查询操作。
RapidXML同样是一个轻量级的XML解析库,性能优异。
它使用模板技术来实现解析功能,具有较高的解析速度和低的内存占用。
RapidXML使用指针和迭代器来遍历XML文档,适用于大型XML文档的处理。
不过,相较于Xerces-C++和TinyXML,RapidXML的API相对简单,不支持DOM方式和XPath查询。
接下来我们来看一下JSON在C++中的处理。
C++同样有一些开源的JSON库可以用来解析和生成JSON数据,其中比较常用的有RapidJSON、JSON for Modern C++、nlohmann/json等。
三种最流行的开放源码XML 库是expat、libxml 和Xerces。
第一部分:DOM解析:概述:DOM解析将会把一个完整的XML文档读进来,生成一个结构树。
这样会要把XML文档全部都加载到内在中。
所以解析起来的速度会要慢一些。
1、如何加载xml文件://创建DOM,加载XML文档MSXML::IXMLDOMDocumentPtr pCommandDoc;pCommandDoc.CreateInstance(__uuidof(MSXML::DOMDocument));pCommandDoc->put_async(V ARIANT_FALSE);pCommandDoc->put_validateOnParse(VARIANT_FALSE);pCommandDoc->put_resolveExternals(V ARIANT_FALSE);pCommandDoc->put_preserveWhiteSpace(V ARIANT_TRUE);pCommandDoc->load(file.GetBuffer(0));2、在XML文档中查找指定的结点://找到MSXML::IXMLDOMNodePtrpRootNode=pCommandDoc->selectSingleNode("root/record");if (pRootNode==NULL){return ;}3、得到XML文档中,结点的属性CString strTemp;MSXML::IXMLDOMNamedNodeMapPtr pAttrs = NULL;pRootNode->get_attributes(&pAttrs);if (pAttrs==NULL){return;}MSXML::IXMLDOMNodePtr pRequestTypeAttr=pAttrs->getQualifiedItem("name","");_bstr_t strRequestType=pRequestTypeAttr->Gettext();strTemp=strRequestType.operator char *();4、得到结点的内容_bstr_t strVisiPort=pNode->Gettext();5、设置结点的内容HRESULT hr=pNode->put_text(_bstr_t(m_strGatewayPassword));6、设置一个属性内容IXMLDOMAttribute *pa=NULL;bstr = SysAllocString(L"属性1");pXMLDom->createAttribute(bstr,&pNode);var = VariantString(L"strin");pa->put_value(var);pRoot->setAttributeNode(pa, &pa1);第二部分、如何使用SAX解析概述:SAX使用的是加载式的,将会把XML文档分断,加载到内存中。
VC++中使用MFC通过ADO连接数据库VC++中使用MFC通过ADO连接数据库一.让我们看看ADO数据库访问技术使用的基本步骤及方法:1.首先,要用#import语句来引用支持ADO的组件类型库(*.tlb),其中类型库可以作为可执行程序(DLL、EXE等)的一部分被定位在其自身程序中的附属资源里,如:被定位在msado15.dll的附属资源中,只需要直接用 #import引用它既可。
可以直接在Stdafx.h文件中加入下面语句来实现:#import "c:/program files/common files/system/ado/msado15.dll"no_namespace rename("EOF", "adoEOF") 【注意,在MFC中路径要用"/"或者"//"】其中路径名可以根据自己系统安装的ADO支持文件的路径来自行设定。
当编译器遇到#import语句时,它会为引用组件类型库中的接口生成包装类,#import语句实际上相当于执行了API涵数LoadTypeLib()。
#import语句会在工程可执行程序输出目录中产生两个文件,分别为*.tlh(类型库头文件)及*.tli(类型库实现文件),它们分别为每一个接口产生智能指针,并为各种接口方法、枚举类型,CLSID等进行声明,创建一系列包装方法。
语句no_namespace说明ADO对象不使用命名空间,rename ("EOF", "adoEOF")说明将ADO中结束标志EOF改为adoEOF,以避免和其它库中命名相冲突。
2.其次,在程序初始过程中需要初始化组件,一般可以用CoInitialize(NULL);来实现,这种方法在结束时要关闭初始化的COM,可以用下面语句CoUnInitialize();来实现。
dlgdata.cpp Line 40 的问题首先打开C->PROGRAM FILE(X86)->Microsoft Visual Studio 11.0->VC->atlmfc->src->mfc->dlgdata.cpp打开,并在LINE40添加断点,调试找出nIDC的值,然后解决问题!如果在resource.h中找不到对应ID,又或者更改过resource.h,出现异常,应删除debug 文件夹,重新生成解决方案!!!重新生成!1.项目属性中“C/C++”->“常规”->“附加包含目录”添加SDK包中的头文件;2.项目属性中“链接器”->“常规”->“附加库目录”把对应的文件夹位置添加进去;3.项目属性中“链接器”->"输入"->“附加依赖项”添加相应的lib文件名。
4.在C***Dlg.h中添加头文件#include"GeneralDef.h"5.在C***App的初始化程序InitInstance()中添加SDK的初始化程序NET_DVR_Init();6.添加成员变量:播放句柄变量LONG m_lPlayHandle; 播放句柄用于判断是否播放正常以及作为NET_DVR_StopRealPlay等函数的句柄参数。
添加成员变量DWORD m_fault_code;BOOL m_bIsLogin;BOOL m_bIsPlaying;STRU_DEVICE_INFO m_struDeviceInfo;并在构造函数中对其初始化m_lPlayHandle = -1;m_fault_code = 0;m_bIsLogin = FALSE;m_bIsPlaying = FALSE;7.在C***Dlg.cpp中添加全局变量char DeviceIp[13] = "192.168.1.11";char UserName[6] = "admin";char Password[10] = "xde123456";WORD DeviceIpPort = 8000;8.单按钮启动if(!m_bIsLogin){NET_DVR_DEVICEINFO_V30 DeviceInfoTmp;memset(&DeviceInfoTmp,0,sizeof(NET_DVR_DEVICEINFO_V30));LONG lLoginID = NET_DVR_Login_V30(DeviceIp , DeviceIpPort, UserName, Password,&DeviceInfoTmp);if(lLoginID == -1){CString strTemp;strTemp.LoadStringW(IDS_STRING_0_LOGIN_STATUS);MessageBox(strTemp);return;}m_bIsLogin = TRUE;m_struDeviceInfo.lLoginID = lLoginID;m_struDeviceInfo.iDeviceChanNum = DeviceInfoTmp.byChanNum;m_struDeviceInfo.iIPChanNum = DeviceInfoTmp.byIPChanNum;m_struDeviceInfo.iStartChan = DeviceInfoTmp.byStartChan;m_struDeviceInfo.iIPStartChan = DeviceInfoTmp.byStartDChan;}if(!m_bIsPlaying){NET_DVR_PREVIEWINFO ClientInfo = {0};ClientInfo.lChannel = 1;//选择预览的窗口句柄ClientInfo.hPlayWnd = GetDlgItem(IDC_0_STATIC_CAMERA)->m_hWnd;m_lPlayHandle = NET_DVR_RealPlay_V40(m_struDeviceInfo.lLoginID, &ClientInfo, NULL, NULL);//预览播放成功返回非负数,失败返回-1if(m_lPlayHandle >= 0){m_bIsPlaying = TRUE;CString strTemp;strTemp.LoadStringW(IDS_STRING_0_PLAY_BUTTON_STATUS2);GetDlgItem(IDC_0_PLAY)->SetWindowText(strTemp);this->SetTimer(Timer_Camera_Connect_Detection, 1000, NULL);}else{CString strTemp1;strTemp1.LoadStringW(IDS_STRING_0_PLAY_STATUS);CString strTemp2;m_fault_code = NET_DVR_GetLastError();strTemp2.Format(L"%d", m_fault_code);CString strTemp3;strTemp3.LoadStringW(IDS_STRING_0_PLAY_FAULT_CODE);CString strTemp4;strTemp4 = strTemp1 + L", " + strTemp3 + strTemp2;MessageBox(strTemp4);return;}}else{m_bIsPlaying = FALSE;CString strTemp;strTemp.LoadStringW(IDS_STRING_0_PLAY_BUTTON_STATUS1);GetDlgItem(IDC_0_PLAY)->SetWindowText(strTemp);NET_DVR_StopRealPlay(m_lPlayHandle);m_lPlayHandle = -1;GetDlgItem(IDC_0_STATIC_CAMERA)->Invalidate();}云台控制1.添加一个基于CButton的CPTZButton类,2.在头文件中添加以下声明#if !defined(AFX_PTZBUTTON_H__B3E99438_BBCE_4862_845F_D3AB668824A6__INCLUDED_) #define AFX_PTZBUTTON_H__B3E99438_BBCE_4862_845F_D3AB668824A6__INCLUDED_#if_MSC_VER > 1000#pragma once#endif// _MSC_VER > 1000并在头文件的结尾加上#endif3.添加成员变量int m_iSubBtnIndex; //功能按钮的索引号,添加按钮类时自动+1,用于对应相应功能添加成员函数void PTZControlAll(LONG lRealHandle,DWORD dwPTZCommand,DWORD dwStop ,int Speed); //用于实现各按钮的功能4.添加全局变量int g_iPtzBtnIndex = 0;在构造函数中对m_iSubBtnIndex进行初始化m_iSubBtnIndex = g_iPtzBtnIndex++;5.通过类向导,添加消息处理函数OnLButtonDown和OnLButtonUp;6.在PTZButton.cpp中添加***app的头文件,并添加声明#ifdef_DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif7.在按钮所在画面的类中添加两个函数,用于获得预览窗口的句柄以及云台移动的速度。
1.建立项目:打开VC++6.0,建立一个基于对话框的MFC应用程序SCommTest;2.在项目中插入MSComm控件选择Project菜单下Add To Project子菜单中的Components and Controls…选项,在弹出的对话框中双击Registered ActiveX Controls项(稍等一会,这个过程较慢),则所有注册过的ActiveX控件出现在列表框中。
选择Microsoft Communications Control, version 6.0,,单击Insert按钮将它插入到我们的Project中来,接受缺省的选项。
(如果你在控件列表中看不到Microsoft Communications Control, version 6.0,那可能是你在安装VC6时没有把ActiveX 一项选上,重新安装VC6,选上ActiveX就可以了),这时在ClassView视窗中就可以看到CMSComm类了,(注意:此类在ClassWizard中看不到,重构clw文件也一样),并且在控件工具栏Controls中出现了电话图标(如图1所示),现在要做的是用鼠标将此图标拖到对话框中,程序运行后,这个图标是看不到的。
3.利用ClassWizard定义CMSComm类控制对象打开ClassWizard->Member Viariables选项卡,选择CSCommTestDlg类,为IDC_MSCOMM1添加控制变量:m_ctrlComm,这时你可以看一看,在对话框头文件中自动加入了//{{AFX_INCLUDES() #i nclude "mscomm.h"//}}AFX_INCLUDES 。
4.在对话框中添加控件向主对话框中添加两个编辑框,一个用于接收显示数据ID为IDC_EDIT_RXDATA,另一个用于输入发送数据,ID为IDC_EDIT_TXDATA,再添加一个按钮,功能是按一次就把发送编辑框中的内容发送一次,将其ID设为IDC_BUTTON_MANUALSEND。
MFC控件使用方法VC2012下MFC程序各控件的常用方法分类:vc控件2013-02-16 16:32 94人阅读评论(0) 收藏举报一下控件的用法全部在VC2012下调试通过,特发文收藏(部分内容来自或参考自网络):Static Text:将ID号改成唯一的一个,如:IDC_XX,然后进一次类向导点确定产生这个ID,之后更改Caption属性:GetDlgItem(IDC_XX)->SetWindowText(L"dsgdhfgdffd");设置字体:CFont *pFont= new CFont;pFont->CreatePointFont(120,_T("华文行楷"));GetDlgItem(IDC_XX)->SetFont(pFont);Edit Control:设置文本:SetDlgItemT ext(IDC_XX,L"iuewurebfdjf");获取所有输入:建立类向导创建一个成员变量(假设是shuru1,shuru2……)类型选value,变量类型任选。
UpdateData(true);GetDlgItem(IDC_XX)->SetWindowText(shuru1);第一句更新所有建立了变量的对话框组件,获取输入的值。
第二句将前面的IDC_XX的静态文本内容改为shuru1输入的内容。
若类型选用control:1.设置只读属性:shuru1.SetReadOnly(true);2.判断edit中光标状态并得到选中内容(richedit同样适用)int nStart,nEnd;CString strTemp;shuru1.GetSel(nStart,nEnd);if(nStart== nEnd){strTemp.Format(_T("光标在%d" ),nStart);AfxMessageBox(strTemp);}else{//得到edit选中的内容shuru1.GetWindowText(strTemp);strTemp= strTemp.Mid(nStart,nEnd-nStart);AfxMessageBox(strTemp);}其中nStart和nEnd分别表示光标的起始和终止位置,从0开始。
VC6.0⾥⾯MFC控件CListCtrl的⼀些常⽤⽤法CListCtrl 使⽤技巧以下未经说明,listctrl默认view 风格为report相关类及处理函数MFC:CListCtrl类SDK:以 “ListView_”开头的⼀些宏。
如 ListView_InsertColumn1. CListCtrl 风格LVS_ICON: 为每个item显⽰⼤图标LVS_SMALLICON: 为每个item显⽰⼩图标LVS_LIST: 显⽰⼀列带有⼩图标的itemLVS_REPORT: 显⽰item详细资料直观的理解:windows资源管理器,“查看”标签下的“⼤图标,⼩图标,列表,详细资料2. 设置listctrl 风格及扩展风格3. 插⼊数据m_list.InsertColumn( 0, "ID", LVCFMT_LEFT, 40 );//插⼊列m_list.InsertColumn( 1, "NAME", LVCFMT_LEFT, 50 );int nRow = m_list.InsertItem(0, “11”);//插⼊⾏m_list.SetItemText(nRow, 1, “jacky”);//设置数据4. ⼀直选中item选中style中的Show selection always,或者在上⾯第2点中设置LVS_SHOWSELALWAYS5. 选中和取消选中⼀⾏int nIndex = 0;//选中m_list.SetItemState(nIndex, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED);//取消选中m_list.SetItemState(nIndex, 0, LVIS_SELECTED|LVIS_FOCUSED);6. 得到listctrl中所有⾏的checkbox的状态m_list.SetExtendedStyle(LVS_EX_CHECKBOXES);CString str;for(int i=0; i {if( m_list.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED || m_list.GetCheck(i)){str.Format(_T("第%d⾏的checkbox为选中状态"), i);AfxMessageBox(str);}}7. 得到listctrl中所有选中⾏的序号⽅法⼀:CString str;for(int i=0; i {if( m_list.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED ) {str.Format(_T("选中了第%d⾏"), i);nbsp; AfxMessageBox(str);}}⽅法⼆:POSITION pos = m_list.GetFirstSelectedItemPosition();if (pos == NULL)TRACE0("No items were selected!\n");else{while (pos){int nItem = m_list.GetNextSelectedItem(pos);TRACE1("Item %d was selected!\n", nItem);// you could do your own processing on nItem here}}8. 得到item的信息TCHAR szBuf[1024];LVITEM lvi;lvi.iItem = nItemIndex;lvi.iSubItem = 0;lvi.mask = LVIF_TEXT;lvi.pszText = szBuf;hTextMax = 1024;m_list.GetItem(&lvi);9. 得到listctrl的所有列的header字符串内容LVCOLUMN lvcol;char str[256];int nColNum;CString strColumnName[4];//假如有4列nColNum = 0;lvcol.mask = LVCF_TEXT;lvcol.pszText = str;hTextMax = 256;while(m_list.GetColumn(nColNum, &lvcol)){strColumnName[nColNum] = lvcol.pszText;nColNum++;}10. 使listctrl中⼀项可见,即滚动滚动条m_list.EnsureVisible(i, FALSE);11. 得到listctrl列数int nHeadNum = m_list.GetHeaderCtrl()->GetItemCount();12. 删除所有列⽅法⼀:while ( m_list.DeleteColumn (0))因为你删除了第⼀列后,后⾯的列会依次向上移动。
●sln:解决方案文件,为解决方案资源管理器提供显示管理文件的图形接口所需的信息。
●csproj:项目文件,创建应用程序所需的引用、数据连接、文件夹和文件的信息。
●.aspx:Web 窗体页由两部分组成:视觉元素(HTML、服务器控件和静态文本)和该页的编程逻辑。
Visual Studio 将这两个组成部分分别存储在一个单独的文件中。
视觉元素在.aspx 文件中创建。
●.ascx:的用户控件(也叫做“pagelets”),是作为一种封装了特定功能和行为(这两者要被用在Web应用程序的各种页面上)的Web页面被开发的。
一个用户控件包含了HTML、代码和其他Web 或者用户控件的组合,并在Web服务器上以自己的文件格式保存,其扩展名是*.ascx。
里的缺省配置并不允许Web客户端通过URL来访问这些文件,但是这个网站的其他页面可以集成这些文件里所包含的功能。
●.aspx.cs:Web 窗体页的编程逻辑位于一个单独的类文件中,该文件称作代码隐藏类文件(.aspx.cs)。
●.cs:类模块代码文件。
业务逻辑处理层的代码。
●.asax:Global.asax 文件(也叫做 应用程序文件)是一个可选的文件,该文件包含响应 或HTTP 模块引发的应用程序级别事件的代码。
●.config:Web.config 文件向它们所在的目录和所有子目录提供配置信息。
●.aspx.resx/.resx:资源文件,资源是在逻辑上由应用程序部署的任何非可执行数据。
通过在资源文件中存储数据,无需重新编译整个应用程序即可更改数据。
●.XSD:XML schema的一种.从DTD,XDR发展到XSD●.pdb:PDB(程序数据库)文件保持着调试和项目状态信息,从而可以对程序的调试配置进行增量链接。
●.suo:解决方案用户选项,记录所有将与解决方案建立关联的选项,以便在每次打开时,它都包含您所做的自定义设置。
●.asmx:asmx :文件包含WebService 处理指令,并用作XML Web services 的可寻址入口点51aspx。
VC++中操作XML(MFC、SDK)XML在Win32程序方面应该没有在Web方面应用得多,很多Win32程序也只是用XML来存存配置信息而已,而且没有足够的好处的话还不如用ini。
VC++里操作XML有两个库可以用:MSXML和XmlLite。
MSXML又细分了两种接口:DOM和SAX2。
XP没自带有XmlLite,只自带有2.x、3.x版的MSXML,不支持SAX2(需要MSXML 4.0以上),所以优先使用DOM。
DOM是以COM形式提供的,VC++里调用DOM可以分3种方法:1、MFC里用CComPtr调用2、SDK里直接调用DOM接口3、SDK里用智能指针调用这3种方法本质上是一样的,区别只不过在于需要编码的多少而已,用CComPtr可以极大的简化代码,下面是几个例子。
例子stocks.xml:<?xml version="1.0"encoding="utf-8"?><root><node1>text1</node1><node2><childnode1attrib1="value1"attrib2="value2"/><childnode2attrib1="value1"attrib2="value2">childtext1</childnode2></node2></root>这个例子应该包含了XML最常见的特征了吧?MFCMFC里可以直接使用DOM,不需要手动添加额外的头文件,只需要在CWinApp::InitInstance()里调用CoInitialize(NULL)初始化COM,在CWinApp::ExitInstance里调用CoUninitialize()释放COM就行了。
//读取XMLCComPtr<IXMLDOMDocument> spDoc;//DOMspDoc.CoCreateInstance(CLSID_DOMDocument);VARIANT_BOOL vb;spDoc->load(CComVariant(OLESTR("stocks.xml")), &vb);//加载XML文件CComPtr<IXMLDOMElement> spRootEle;spDoc->get_documentElement(&spRootEle);//根节点CComPtr<IXMLDOMNodeList> spNodeList;spRootEle->get_childNodes(&spNodeList);//子节点列表long nLen;spNodeList->get_length(&nLen);//子节点数for(long i =0; i != nLen;++i)//遍历子节点{CComPtr<IXMLDOMNode> spNode;spNodeList->get_item(i, &spNode);ProcessNode(spNode);//节点处理函数}//写入XMLCComPtr<IXMLDOMNode> spNode;spRootEle->selectSingleNode(OLESTR("/root/node1"), &spNode);spNode->put_text(OLESTR("newText"));//写入textspRootEle->selectSingleNode(OLESTR("/root/node2/childnode1/@attrib1"), &spNode); spNode->put_nodeValue(CComVariant(OLESTR("newValue")));//写入valueCComPtr<IXMLDOMNode> spNewNode;spDoc->createNode(CComVariant(NODE_ELEMENT), OLESTR("childnode3"), OLESTR(""), &spNewNode);//创建新节点spRootEle->selectSingleNode(OLESTR("/root/node2"), &spNode);spNode->appendChild(spNewNode, &spNewNode);//将新节点加为node2的子节点spNewNode->put_text(OLESTR("childtext2"));//写入新节点textCComQIPtr<IXMLDOMElement> spEle = spNewNode;//注意这里使用CComQIPtrspEle->setAttribute(OLESTR("attrib1"), CComVariant(OLESTR("value1")));//给新节点添加属性spDoc->save(CComVariant(OLESTR("stocks.xml")));//节点处理函数void ProcessNode(CComPtr<IXMLDOMNode>& spNode){CComBSTR bsNodeName;spNode->get_nodeName(&bsNodeName);//节点名AfxMessageBox(COLE2CT(bsNodeName));CComVariant varVal;spNode->get_nodeValue(&varVal);//节点值AfxMessageBox(COLE2CT(varVal.bstrVal));DOMNodeType eNodeType;spNode->get_nodeType(&eNodeType);if(eNodeType == NODE_ELEMENT)//只有NODE_ELEMENT类型才能包含有属性和子节点{//递归遍历节点属性CComPtr<IXMLDOMNamedNodeMap> spNameNodeMap;spNode->get_attributes(&spNameNodeMap);long nLength;spNameNodeMap->get_length(&nLength);for(long i =0; i != nLength;++i){CComPtr<IXMLDOMNode> spNodeAttrib;//注意属性也是一个IXMLDOMNode spNameNodeMap->get_item(i, &spNodeAttrib);ProcessNode(spNodeAttrib);}//递归遍历子节点CComPtr<IXMLDOMNodeList> spNodeList;spNode->get_childNodes(&spNodeList);spNodeList->get_length(&nLength);for(long i =0; i != nLength;++i){CComPtr<IXMLDOMNode> spChildNode;spNodeList->get_item(i, &spChildNode);ProcessNode(spChildNode);}}}对于<tag>text</tag>这样的节点,get_nodeValue会得到空,要得到"text"的话可以遍历子节点(只有一个子节点,它的nodeName为"#text",nodeType为NODE_TEXT,nodeValue就是"text");也可以用get_text 直接得到"text",但是对于这样的节点<tag>text<childtag>childtext</childtag></tag>,get_text会同时得到"text"和"childtext",不过这样的节点应该是不允许的。
DOM里使用的字符串(BSTR)都是OLESTR类型,默认情况下OLESTR是Unicode字符,MFC里可以用COLE2CT把LPCOLESTR转换为LPCTSTR。
对于自己定义的XML,大多数时候不需要遍历,可以通过调用selectNodes、selectSingleNode指定XPath 直接读取某个节点或属性:CComPtr<IXMLDOMDocument> spDoc;//DOMspDoc.CoCreateInstance(CLSID_DOMDocument);VARIANT_BOOL vb;spDoc->load(CComVariant(OLESTR("stocks.xml")), &vb);//加载XML文件CComPtr<IXMLDOMElement> spRootEle;spDoc->get_documentElement(&spRootEle);//根节点CComPtr<IXMLDOMNodeList> spNodeList;CComPtr<IXMLDOMNode> spNode;spRootEle->selectNodes(OLESTR("/root/node2/*"), &spNodeList);//得到node2下的所有子节点spRootEle->selectSingleNode(OLESTR("/root/node2/childnode1/@attrib1"), &spNode);//得到childnode1的attrib1属性XPath的语法可以参考XML文档或MSDN。