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>
<childnode1 attrib1="value1" attrib2="value2"/>
<childnode2 attrib1="value1" attrib2="value2">childtext1</childnode2>
</node2>
</root>

这个例子应该包含了XML最常见的特征了吧?

MFC
MFC里可以直接使用DOM,不需要手动添加额外的头文件,只需要在CWinApp::InitInstance()里调用CoInitialize(NULL)初始化COM,在CWinApp::ExitInstance里调用CoUninitialize()释放COM就行了。

//读取XML
CComPtr<IXMLDOMDocument> spDoc; //DOM
spDoc.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); //节点处理函数
}

//写入XML
CComPtr<IXMLDOMNode> spNode;
spRootEle->selectSingleNode(OLESTR("/root/node1"), &spNode);
spNode->put_text(OLESTR("newText")); //写入text
spRootEle->selectSingleNode(OLESTR("/root/node2/childnode1/@attrib1"), &spNode);
spNode->put_nodeValue(CComVariant(OLESTR("newValue"))); //写入value
CComPtr<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")); //写入新节点text
CComQIPtr<IXMLDOMElement> spEle = spNewNode; //注意这里使用CComQIPtr
spEle->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; //DOM
spDoc.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。

SDK
SDK中也可以使用智能指针,和MFC没太大区别,同样很方便,直接给代码:

#include <iostream>
#include <tchar.h>

#import <msxml3.dll>

//节点处理函数
void ProcessNode(MSXML2::IXMLDOMNodePtr spNode)
{
std::cout << "nodeName: " << spNode->nodeName;
if (spNode->nodeType == NODE_ATTRIBUTE || spNode->nodeType == NODE_TEXT)
std::cout << "\tnodeValue: " << _bstr_t(spNode->nodeValue);
std::cout << std::endl;

if (spNode->nodeType == NODE_ELEMENT)
{
MSXML2::IXMLDOMNamedNodeMapPtr spNameNodeMap = spNode->attributes;
for (long i = 0; i != spNameNodeMap->length; ++i) //遍历节点属性
ProcessNode(spNameNodeMap->item[i]);

MSXML2::IXMLDOMNodeListPtr spNodeList = spNode->childNodes;
for (long i = 0; i != spNodeList->length; ++i) //遍历子节点
ProcessNode(spNodeList->item[i]);
}
}

int _tmain(int argc, _TCHAR* argv[])
{
CoInitialize(NULL);
//读取XML
MSXML2::IXMLDOMDocumentPtr spXMLDoc;
spXMLDoc.CreateInstance(__uuidof(MSXML2::DOMDocument30));
spXMLDoc->load(L"stocks.xml");
MSXML2::IXMLDOMElementPtr spRoot = spXMLDoc->documentElement; //根节点
MSXML2::IXMLDOMNodeListPtr spNodeList = spRoot->childNodes;
for (long i = 0; i != spNodeList->length; ++i) //遍历子节点
ProcessNode(spNodeList->item[i]);

//写入XML
spRoot->selectSingleNode(L"/root/node1")->text = L"newText";
spRoot->selectSingleNode(L"/root/node2/childnode1/@attrib1")->nodeValue = L"newValue";
MSXML2::IXMLDOMNodePtr spNewNode = spRoot->selectSingleNode(L"/root/node2")->appendChild(
spXMLDoc->createNode(_variant_t(NODE_ELEMENT), L"childnode3", L"")
); //给node2创建新子节点childnode3
spNewNode->text = L"childtext2";
MSXML2::IXMLDOMElementPtr spEle = spNewNode;
spEle->setAttribute(L"attrib1", _variant_t(L"value1")); //添加新属性
spXMLDoc->save(_variant_t(L"stocks.xml"));

spNewNode.Release();
spEle.Release();
spNodeList.Release();
spRoot.Release();
spXMLDoc.Release();
CoUninitialize();

system("pause");
return 0;
}

[转]VC++中操作XML(MFC、SDK)的更多相关文章

  1. VC++中操作XML(MFC、SDK)转

    [转]VC++中操作XML(MFC.SDK) XML在Win32程序方面应该没有在Web方面应用得多,很多Win32程序也只是用XML来存存配置信息而已,而且没有足够的好处的话还不如用ini.VC++ ...

  2. VC++中操作XMLWin32实例

    摘要:VC++中操作XML XML在Win32程序方面应该没有在Web方面应用得多,很多Win32程序也只是用XML来存存配置信息而已,而且没有足够的好处的话还不如用ini.VC++里操作XML有两个 ...

  3. VBA中操作XML

    OFFICE2007之后使用了OpenXml标准(伟大的改变),定制文本级的Ribbon可以通过修改压缩包内的xml文件来实现. 先学习一下VBA中操作XML的方法 先引用Microsoft XML ...

  4. 数据库中操作XML(openXML)

    最近公司项目需要在数据库中操作XML,因此系统的学习了一下 一.openxml的格式 OPENXML( idoc int [ in] , XPathnvarchar [ in ] , [ flags ...

  5. C#.Net中操作XML方法一

    我们知道XML是一种可标记性的语言,用来标记数据.定义数据类型,是一种执行用户对自己的标记语言进行定义的源语言.由于结构好.而且easy理解,就好比一棵树,层次关系分明,因此也经常把一些数据存储到XM ...

  6. C#中操作xml文件(插入节点、修改、删除)

    已知有一个xml文件(bookstore.xml)如下: <?xml version="1.0" encoding="gb2312"?> <b ...

  7. 第12章 在.NET中操作XML

    12.1 XML概述 12.1.1 为什么要有XML 12.1.2 XML文档结构 (1)文档声明 <?xml version="1.0"encoding="UTF ...

  8. Flex中操作XML的E4X方法

    用于处理 XML 的 E4X 方法 Flash Player 9 和更高版本,Adobe AIR 1.0 和更高版本   ECMAScript for XML 规范定义了一组用于使用 XML 数据的类 ...

  9. VC,VB操作XML

    TCHAR buffer[MAX_PATH] = {}; ::GetModuleFileName(NULL, buffer, MAX_PATH); CString strPath = buffer; ...

随机推荐

  1. python 图像识别转文字

    rom PIL import Image import pytesseract #上面都是导包,只需要下面这一行就能实现图片文字识别 #text=pytesseract.image_to_string ...

  2. MIDI制作的相关软件

    Native Instruments Kontakt(音乐采样器) fl studio 12 v12.5.0.59 汉化版水果   http://xiazai.flstudiochina.com/wm ...

  3. mysqldump导入导出详解

    mysqldump可以指定路径的,如果没指定路径,而只写了文件名的话,那么就在当前进入mysql命令行所在的目录,也就是mysql安装目录下 mysqldump  --default-characte ...

  4. docker安全最佳实践概述

    /************************************************* * Author : Samson * Date : 08/07/2015 * Test plat ...

  5. 系统安全-LDAP

    LDAP服务器 1.目录服务  目录是一个为查询.浏览和搜索而优化的专业分布式数据库,它呈树状结构组织数据,就好像Linux/Unix系统中的文件目录一样.目录数据库和关系数据库不同,它有优异的读性能 ...

  6. ubuntu 16.04 更新 gcc/g++ 4.9.2

    ubuntu 转载 2016年10月12日 :: 标签:ubuntu /g++ /gcc [html] view plain copy sudo dpkg -l g++ 最近在学C++primer , ...

  7. JavaScript读书笔记(1)

    从今天开启每天看书记笔记模式,<JavaScript高级程序设计(第3版)> 1. Javascript最初是为了解决输入验证器的问题,现在已经发展成一门复杂的语言: 2.  语言标准为E ...

  8. 【caffe-windows】 caffe-master 之图片转换成lmdb or leveldb

    前期准备: 文件夹train:此文件夹中按类别分好子文件夹,各子文件夹里存放相应图片 文件夹test:同train,有多少类就有多少个子文件夹 trainlabels.txt : 存的是训练集的标签  ...

  9. dsoframer注冊说明及在VC2010使用

    一.dsoframer在XP.win7和win8中的注冊方法. 从微软站点下载DsoFrmaer_KB311765_x86.exe,双击解开后得到的dsoframer.ocx等文件. (一)XP注冊 ...

  10. poj 1163 The Triangle &amp;poj 3176 Cow Bowling (dp)

    id=1163">链接:poj 1163 题意:输入一个n层的三角形.第i层有i个数,求从第1层到第n层的全部路线中.权值之和最大的路线. 规定:第i层的某个数仅仅能连线走到第i+1层 ...