分享
 
 
 

C++中处理XML文件

王朝c/c++·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

写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:\\test.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"\r\n", (DWORD)(2*sizeof(WCHAR)), &dwBytesWritten, NULL);

attributeID->Release(); attributeID = NULL;

}

else

{

WriteFile(logFile, L"\r\n", (DWORD)(2*sizeof(WCHAR)), &dwBytesWritten, NULL);

}

attributes->Release(); attributes = NULL;

}

else

{

WriteFile(logFile, L"\r\n", (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"\r\n", (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(xmlRoot!=NULL)

xmlRoot->Release();

return 0;

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有