[转载]C++中处理XML文件
写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(¤tNode)) && 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(¤tNode)) && 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文件的更多相关文章
- 修改Android中strings.xml文件, 动态改变数据
有些朋友可能会动态的修改Android中strings.xml文件中的值,在这里给大家推荐一种简单的方法.strings.xml中节点是支持占位符的,如下所示: <string name=&qu ...
- .net中创建xml文件的两种方法
.net中创建xml文件的两种方法 方法1:根据xml结构一步一步构建xml文档,保存文件(动态方式) 方法2:直接加载xml结构,保存文件(固定方式) 方法1:动态创建xml文档 根据传递的值,构建 ...
- [Eclipse] eclipse中打开xml文件,使用ctrl+鼠标左键无法跳转至Java源文件【待解决】
eclipse中打开xml文件,使用ctrl+鼠标左键无法跳转至Java源文件: 1. 设置eclipse ctrl + 左键打开源文件代码,如下图,设置都正常 2. 在网上找了很多种办法,均失败,在 ...
- 解决Eclipse中编辑xml文件的智能提示问题,最简单的是第二种方法。
Eclipse for Android xml 文件代码自动提示功能,介绍Eclipse 编辑器中实现xml 文件代码自动智能提示功能,解决eclipse 代码提示失效.eclipse 不能自动提示. ...
- [转]解决Eclipse中编辑xml文件的智能提示问题
转自:http://hi.baidu.com/cghroom/item/48fd2d0dc1fc23c675cd3c3e 摘要: Eclipse for Android xml 文件代码自动提示功能 ...
- 关于Java Webproject中web.xml文件
提及Java Webproject中web.xml文件无人不知,无人不识,呵呵呵:系统首页.servlet.filter.listener和设置session过期时限.张口就来,但是你见过该文件里的e ...
- 谈谈对XML的理解?说明Web应用中Web.xml文件的作用?
谈谈对XML的理解?说明Web应用中Web.xml文件的作用? 解答:XML(Extensible Markup Language)即可扩展标记语言,它与HTML一样,都是SGML(Standard ...
- XML(php中获取xml文件的方式/ajax获取xml格式的响应数据的方式)
1.XML 格式规范: ① 必须有一个根元素 ② 不可有空格.不可以数字或.开头.大小写敏感 ③ 不可交叉嵌套 ④ 属性双引号(浏览器自动修正成双引号了) ⑤ 特殊符号要使用实体 ⑥ 注释和HTML一 ...
- opencv局限:cv::FileStorage读取中,xml文件的第一层节点不能超过4个
今天测试发现一个问题,cv::FileStorage读取中,xml文件的第一层节点不能超过4个. <?xml version="1.0"?> <opencv_st ...
随机推荐
- [BZOJ1815&BZOJ1488]有色图/图的同构(Polya定理)
由于有很多本质相同的重复置换,我们先枚举各种长度的点循环分别有多少个,这个暴搜的复杂度不大,n=53时也只有3e5左右.对于每种搜索方案可以轻易求出它所代表的置换具体有多少个. 但我们搜索的是点置换组 ...
- OPENCV----在APP性能测试中的应用(一)
应用项目: APP的性能测试 应用场景: APP启动速度 视频开播速度 加载速度 等~~ 缘来: 基于APP日志和UiAutomator的测试方案,测试结果不能直白且精确的反应,用户的体验 ...
- 获取不到offsetHeight问题
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- js面向对象写页面
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- java并发基础(二)
<java并发编程实战>终于读完4-7章了,感触很深,但是有些东西还没有吃透,先把已经理解的整理一下.java并发基础(一)是对前3章的总结.这里总结一下第4.5章的东西. 一.java监 ...
- spring mvc 如何传递集合参数(list,数组)
spring mvc 可以自动的帮你封装参数成为对象,不用自己手动的通过request一个一个的获取参数,但是这样自动的参数封装碰碰到了集合参数可能就需要点小技巧才可以了. 一.基础类型和引用类型有什 ...
- 转 UIAlertView 不显示、屏幕变灰
UIAlertView 不显示.屏幕变灰 SvenFang 票 在 [[NSNotificationCenter defaultCenter] addObserver:self selector:@s ...
- 学习 KJFrameForAndroid
简介 KJFrameForAndroid 又叫KJLibrary,是一个android的orm 和 ioc 框架.同时封装了android中的Bitmap与Http操作的框架,使其更加简单易用:KJF ...
- 视图Ext.Viewport和窗口Ext.Window用法
Viewport不需要再指定renderTo,而我们也看到Viewport确实填充了整个浏览器显示区域,并会随着浏览器显示区域大小的改变而改改.他有三个特点: 1).创建即可使用.不需要渲染,当组件在 ...
- 告别恶心的CGRect设置
FrameAccessor https://github.com/AlexDenisov/FrameAccessor Manual Install(手动安装) All you need to do i ...