写Unmanaged Code在.NET时代成为一种很悲惨的事,当你需要处理XML文件时,这种感觉会变得尤其强烈。FCL中的System.XML多简单啊,连Steve Ballmer都知道怎么用。 

事情不会总是那么理想的,假如你要在C/C++程序里处理XML怎么办呢? 

选择一:市面上的XML lib还是有几个的,最有名的当然是libXML。我一年前用过,很不错,我还特意写了一份简明教程,后来不知搁哪儿了。 

选择二:MS的MSXML,我要介绍的就是这个。 

先说一下在MSDN哪里找文档吧,往下看的时候也好有个参考:在Index里打:Windows Media Services 9 Series SDK=>Programming Reference=>Programming Reference (C++)=>XML DOM Interfaces (C++)。什么?Windows Media?呵呵,不错,我觉得这个guide反而是最清楚的,你直接找MSXML,得到的结果,我觉得还没这个好。 

在C程序里调用MSXML基本就是一堆COM接口,不过在Visual Studio里操作先要做点简单的设置: 

在你的Project里Add References=>COM标签=>Microsoft XML v4.0,5.0其实也有了,但因为是和Office一起发布的,觉得有点怪,不想用,反正也未必用什么很怪异的功能,4.0可以了。 

然后在加入这两行: 

#include <msXML2.h> 
#import <msXML4.dll> 

头文件和dll库。什么?在哪里加?头文件或者c/cpp文件啊,哪里合适放哪儿。 

然后就开始编程了,先定义两个必用的变量: 

IXMLDOMDocumentPtr XMLFile = NULL; 
IXMLDOMElement* XMLRoot = NULL; 

为什么是必用的?  汗... 

第一步当然是初始化COM: 

if(FAILED(CoInitialize(NULL))) .... 

接下来初始化XMLFile对象: 

if(FAILED(XMLFile.CreateInstance("MsXML2.DOMDocument.4.0"))) ... 

然后就可以加载XML文件了: 

_variant_t varXML(L"C: est.XML"); //L for unicode 
VARIANT_BOOL varOut; 
XMLFile->load(varXML, &varOut); 

取得root element: 

XMLFile->get_documentElement(&XMLRoot)) 

取得第一级element: 

IXMLDOMNodeList* XMLChildNodes = NULL; 
XMLRoot->get_childNodes(&XMLChildNodes); 

遍历所有第一级element: 

IXMLDOMNode* currentNode = NULL; 
while(!FAILED(XMLChildNodes->nextNode(&currentNode)) && currentNode != NULL) 

//do something 

取得当前element的名称: 

BSTR nodeName; 
currentNode->get_nodeName(&nodeName); 

取得当前element的一个attribute(假设这个attribute叫type)的值: 

IXMLDOMNamedNodeMap* attributes = NULL; 
IXMLDOMNode* attributeName = NULL; 
_bstr_t bstrAttributeName = "type"; 
BSTR nameVal; 
currentNode->get_attributes(&attributes); 
attributes->getNamedItem(bstrAttributeName, &attributeName); 
attributeName->get_text(&nameVal); 

需要注重的是,你要记住释放所有的借口,IXMLDOM***->Release(),这可不是.NET,有人帮你GC,你得自己调用Release()来减reference count,it's COM, remember? 

好了,大致就这样,顺便提一下XPath: 

_bstr_t bstrXMLQuery = L"/books/book[@type=scifi and @author=fox]"; 

IXMLDOMNodeList* nodes = NULL; 
if(FAILED(XMLRoot->selectNodes(bstrXMLQuery, &nodes)) FAILED(nodes->get_length(&length)) length == 0) 
//no match found or something went wrong 
else 
//match found 

上面是找这样的node: 

<books> 
<book type="scifi" author="fox">.... 
</book> 
.... 
</books> 

具体的XPath语法就查手册吧,到处都有。 

哦,对了,忘了说:假如你全部用ATL的类的话,借口的调用会简单一点,不过很轻易转换的,比如: 

IXMLDOMDocument* 对应 IXMLDOMDocumentPtr(我这里用了),其他基本也是加个Ptr,我不废话了。 

最后提供一个sample,我临时攒的。工作的时候写的程序当然不能拿来贴的,呵呵。这个sample基本就是遍历整个XML,然后报告一遍文件的结构,对每个node,假如它有一个叫id的attribute,就同时打印id的值。If you want the complete VS project, shoot me an email. But I guess no one really needs it anyway, right, : ) 

#include "stdafx.h" 
#include <windows.h> 
#include <msXML2.h> 
#import <msXML4.dll> 

HANDLE logFile = NULL; 

#define INDENT 4 

#define TESTHR(hr) 

if(FAILED(hr)) goto fail; 

void PrintChild(IXMLDOMNodeList* nodeList, int level) 

if(nodeList == NULL) 
return; 

IXMLDOMNode* currentNode = NULL; 
IXMLDOMNodeList* childNodes = NULL; 
IXMLDOMNamedNodeMap* attributes = NULL; 
IXMLDOMNode* attributeID = NULL; 

while(!FAILED(nodeList->nextNode(&currentNode)) && currentNode != NULL) 

BSTR nodeName; 
TESTHR(currentNode->get_nodeName(&nodeName)); 
DWord dwBytesWritten; 
for(int i=0; i<level*INDENT; i++) 
WriteFile(logFile, L" ", (Dword)(sizeof(WCHAR)), &dwBytesWritten, NULL); 

//WCHAR msg[MAX_SIZE]; 
//wsprintf(msg, L"%s ", nodeName); 
WriteFile(logFile, nodeName, (Dword)(wcslen(nodeName)*sizeof(WCHAR)), &dwBytesWritten, NULL); 

TESTHR(currentNode->get_attributes(&attributes)); 
if(attributes!=NULL) 

_bstr_t bstrAttributeName = "id"; 
BSTR idVal; 
TESTHR(attributes->getNamedItem(bstrAttributeName, &attributeID)); 
if(attributeID != NULL) 

TESTHR(attributeID->get_text(&idVal)); 
WriteFile(logFile, L" ", (Dword)(sizeof(WCHAR)), &dwBytesWritten, NULL); 
WriteFile(logFile, idVal, (Dword)(wcslen(idVal)*sizeof(WCHAR)), &dwBytesWritten, NULL); 
WriteFile(logFile, L" ", (Dword)(2*sizeof(WCHAR)), &dwBytesWritten, NULL); 
attributeID->Release(); attributeID = NULL; 

else 

WriteFile(logFile, L" ", (Dword)(2*sizeof(WCHAR)), &dwBytesWritten, NULL); 


attributes->Release(); attributes = NULL; 


else 

WriteFile(logFile, L" ", (Dword)(2*sizeof(WCHAR)), &dwBytesWritten, NULL); 

TESTHR(currentNode->get_childNodes(&childNodes)); 
PrintChild(childNodes, level+1); 
currentNode=NULL; 

fail: 
if(childNodes!=NULL) 
childNodes->Release(); 
if(attributeID!=NULL) 
attributeID->Release(); 
if(attributes!=NULL) 
attributes->Release(); 
if(currentNode != NULL) 
currentNode->Release(); 

int _tmain(int argc, _TCHAR* argv[]) 

IXMLDOMDocumentPtr XMLFile = NULL; 
IXMLDOMElement* XMLRoot = NULL; 
_variant_t varXML(L"C:demo1.XML"); 

logFile = CreateFile(L"log.txt", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 
if(logFile == INVALID_HANDLE_VALUE) 
goto fail; 

TESTHR(CoInitialize(NULL)); 

TESTHR(XMLFile.CreateInstance("MsXML2.DOMDocument.4.0")); 

VARIANT_BOOL varOut; 
TESTHR(XMLFile->load(varXML, &varOut)); 

TESTHR(XMLFile->get_documentElement(&XMLRoot)); 

BSTR rootName; 
Dword dwBytesWritten; 
TESTHR(XMLRoot->get_nodeName(&rootName)); 
WriteFile(logFile, rootName, (Dword)(wcslen(rootName)*sizeof(WCHAR)), &dwBytesWritten, NULL); 
WriteFile(logFile, L" ", (Dword)(2*sizeof(WCHAR)), &dwBytesWritten, NULL); 

IXMLDOMNodeList* XMLChildNodes = NULL; 
TESTHR(XMLRoot->get_childNodes(&XMLChildNodes)); 

PrintChild(XMLChildNodes, 2); 

fail: 
if(logFile != INVALID_HANDLE_VALUE) 
CloseHandle(logFile); 
if(XMLChildNodes!=NULL) 
XMLChildNodes->Release(); 
if 
 

 

原文来自
http://school.cnd8.com/c/jiaocheng/10145.htm

 

[转载]C++中处理XML文件的更多相关文章

  1. 修改Android中strings.xml文件, 动态改变数据

    有些朋友可能会动态的修改Android中strings.xml文件中的值,在这里给大家推荐一种简单的方法.strings.xml中节点是支持占位符的,如下所示: <string name=&qu ...

  2. .net中创建xml文件的两种方法

    .net中创建xml文件的两种方法 方法1:根据xml结构一步一步构建xml文档,保存文件(动态方式) 方法2:直接加载xml结构,保存文件(固定方式) 方法1:动态创建xml文档 根据传递的值,构建 ...

  3. [Eclipse] eclipse中打开xml文件,使用ctrl+鼠标左键无法跳转至Java源文件【待解决】

    eclipse中打开xml文件,使用ctrl+鼠标左键无法跳转至Java源文件: 1. 设置eclipse ctrl + 左键打开源文件代码,如下图,设置都正常 2. 在网上找了很多种办法,均失败,在 ...

  4. 解决Eclipse中编辑xml文件的智能提示问题,最简单的是第二种方法。

    Eclipse for Android xml 文件代码自动提示功能,介绍Eclipse 编辑器中实现xml 文件代码自动智能提示功能,解决eclipse 代码提示失效.eclipse 不能自动提示. ...

  5. [转]解决Eclipse中编辑xml文件的智能提示问题

    转自:http://hi.baidu.com/cghroom/item/48fd2d0dc1fc23c675cd3c3e 摘要:  Eclipse for Android xml 文件代码自动提示功能 ...

  6. 关于Java Webproject中web.xml文件

    提及Java Webproject中web.xml文件无人不知,无人不识,呵呵呵:系统首页.servlet.filter.listener和设置session过期时限.张口就来,但是你见过该文件里的e ...

  7. 谈谈对XML的理解?说明Web应用中Web.xml文件的作用?

    谈谈对XML的理解?说明Web应用中Web.xml文件的作用? 解答:XML(Extensible Markup Language)即可扩展标记语言,它与HTML一样,都是SGML(Standard ...

  8. XML(php中获取xml文件的方式/ajax获取xml格式的响应数据的方式)

    1.XML 格式规范: ① 必须有一个根元素 ② 不可有空格.不可以数字或.开头.大小写敏感 ③ 不可交叉嵌套 ④ 属性双引号(浏览器自动修正成双引号了) ⑤ 特殊符号要使用实体 ⑥ 注释和HTML一 ...

  9. opencv局限:cv::FileStorage读取中,xml文件的第一层节点不能超过4个

    今天测试发现一个问题,cv::FileStorage读取中,xml文件的第一层节点不能超过4个. <?xml version="1.0"?> <opencv_st ...

随机推荐

  1. luoguP3871 [TJOI2010]中位数

    题目链接 luoguP3871 [TJOI2010]中位数 题解 平衡树 代码 #include<vector> #include<cstdio> #include<cs ...

  2. 1316 文化之旅 2012年NOIP全国联赛普及组

      题目描述 Description 有一位使者要游历各国,他每到一个国家,都能学到一种文化,但他不愿意学习任何一种文化超过一次(即如果他学习了某种文化,则他就不能到达其他有这种文化的国家).不同的国 ...

  3. codevs 1052 地鼠游戏 优先队列

    1052 地鼠游戏 Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://www.codevs.cn/problem/1052/ Descriptio ...

  4. POJ 3061 Subsequence 尺取法,一个屌屌的O(n)算法

    Subsequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9050   Accepted: 3604 Descr ...

  5. 设置Nginx开机自启动

    Nginx 是一个很强大的高性能Web和反向代理服务器.虽然使用命令行可以对nginx进行各种操作,比如启动等,但是还是根据不太方便.下面介绍在linux下安装后,如何设置开机自启动. 首先,在lin ...

  6. This seems to be a pre-built javascript file. webpack报这个警告怎么办?

    增加 module.noParse 进行解决 例如: { resolve: { alias: { 'react': 'my/react/path' } }, module: { noParse: [/ ...

  7. Oracle VM VisualBox 虚拟机创建共享文件夹。

    先来啰嗦几句,公司的电脑用的是 VMware10的虚拟机  相信大家都很熟悉了   VMware 创建共享文件功能可以直接安装tools来实现 但是 Oracle VM VisualBox  第一次玩 ...

  8. Reverse Engineering the NC ECU (revisited) -- SH7508

    http://forum.miata.net/vb/showthread.php?t=536601 Hey all! About 5 years ago, there was a great thre ...

  9. Linux新内核:提升系统性能 --Linux运维的博客

    http://blog.csdn.net/linuxnews/article/details/52864182

  10. C#引用类型转换的几种方式

    本篇体验引用类型转换:子类转换成父类,父类转换成子类,以及不是子父级关系类之间的转换. □ 隐式转换:子类转换成父类 public class Animal { public int _age; pu ...