当前位置: 首页 > news >正文

从0到1使用C++操作MSXML

1. 引言

MSXML(Microsoft XML Core Services)是微软提供的一套用于处理XML的COM组件库,广泛应用于Windows平台的XML解析、验证、转换等操作。本文将详细介绍如何从零开始,在C++中使用MSXML解析和操作XML文件,包含完整的代码示例及逐行注释,帮助初学者快速上手。


2. 准备工作

2.1 环境要求

  • Windows 操作系统(MSXML 是 Windows 特有组件)
  • Visual Studio(推荐 2015 或更高版本)
  • 基础C++知识(COM组件基本概念)

2.2 引入MSXML库

在代码中引入MSXML头文件,并链接对应的库:

#include <msxml6.h>   // MSXML 6.0(最新稳定版)
#include <comdef.h>   // 用于COM智能指针(_bstr_t, _variant_t)
#pragma comment(lib, "msxml6.lib")  // 链接MSXML库

3. 初始化COM环境

MSXML基于COM(Component Object Model),使用前必须初始化COM库:

#include <objbase.h>  // CoInitializeEx 所需头文件int main() {// 初始化COM库(单线程模式)HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);if (FAILED(hr)) {printf("Failed to initialize COM. Error: %08X\n", hr);return 1;}// 后续代码...// 释放COM库CoUninitialize();return 0;
}

逐行解析:

  1. CoInitializeEx(NULL, COINIT_APARTMENTTHREADED):初始化COM,指定单线程单元(STA)模式。
  2. FAILED(hr):检查COM初始化是否成功。
  3. CoUninitialize():程序结束时释放COM资源。

4. 加载并解析XML文件

4.1 创建MSXML DOM对象

IXMLDOMDocument2* pXMLDoc = NULL;
hr = CoCreateInstance(__uuidof(DOMDocument60),  // 使用MSXML 6.0NULL,CLSCTX_INPROC_SERVER,__uuidof(IXMLDOMDocument2),(void**)&pXMLDoc
);
if (FAILED(hr) || pXMLDoc == NULL) {printf("Failed to create XML DOM instance. Error: %08X\n", hr);CoUninitialize();return 1;
}

逐行解析:

  1. CoCreateInstance:创建MSXML DOM对象。
  2. __uuidof(DOMDocument60):指定使用MSXML 6.0。
  3. CLSCTX_INPROC_SERVER:组件运行在进程内。

4.2 加载XML文件

VARIANT_BOOL bSuccess = VARIANT_FALSE;
hr = pXMLDoc->load(_variant_t(L"example.xml"), &bSuccess);
if (FAILED(hr) || bSuccess != VARIANT_TRUE) {printf("Failed to load XML file. Error: %08X\n", hr);pXMLDoc->Release();CoUninitialize();return 1;
}

逐行解析:

  1. pXMLDoc->load:加载XML文件(example.xml)。
  2. _variant_t(L"example.xml"):将文件名转换为COM兼容的VARIANT类型。
  3. bSuccess:返回加载是否成功。

5. 读取XML数据

5.1 获取XML根节点

IXMLDOMElement* pRoot = NULL;
hr = pXMLDoc->get_documentElement(&pRoot);
if (FAILED(hr) {printf("Failed to get root element. Error: %08X\n", hr);pXMLDoc->Release();CoUninitialize();return 1;
}

逐行解析:

  1. get_documentElement:获取XML的根节点。

5.2 遍历子节点

IXMLDOMNodeList* pNodes = NULL;
hr = pRoot->get_childNodes(&pNodes);
if (FAILED(hr)) {printf("Failed to get child nodes. Error: %08X\n", hr);pRoot->Release();pXMLDoc->Release();CoUninitialize();return 1;
}long length = 0;
pNodes->get_length(&length);  // 获取子节点数量for (long i = 0; i < length; i++) {IXMLDOMNode* pNode = NULL;pNodes->get_item(i, &pNode);  // 获取第i个节点BSTR nodeName;pNode->get_nodeName(&nodeName);  // 获取节点名称printf("Node %d: %S\n", i, nodeName);SysFreeString(nodeName);  // 释放BSTR内存pNode->Release();  // 释放节点
}
pNodes->Release();

逐行解析:

  1. get_childNodes:获取所有子节点。
  2. get_length:获取子节点数量。
  3. get_item(i, &pNode):获取第i个节点。
  4. get_nodeName:获取节点名称(返回BSTR,需手动释放)。

6. 修改XML数据

6.1 修改节点属性

IXMLDOMElement* pFirstChild = NULL;
pNodes->get_item(0, (IXMLDOMNode**)&pFirstChild);  // 获取第一个子节点// 设置属性
hr = pFirstChild->setAttribute(_bstr_t(L"newAttr"),  // 属性名_variant_t(L"newValue")  // 属性值
);
if (FAILED(hr)) {printf("Failed to set attribute. Error: %08X\n", hr);
}
pFirstChild->Release();

逐行解析:

  1. setAttribute:设置节点属性,使用_bstr_t_variant_t封装字符串。

6.2 保存修改后的XML

hr = pXMLDoc->save(_variant_t(L"modified.xml"));
if (FAILED(hr)) {printf("Failed to save XML. Error: %08X\n", hr);
}

逐行解析:

  1. save:保存XML到新文件。

7. 完整代码示例

演示1

#include <msxml6.h>
#include <comdef.h>
#include <objbase.h>
#include <stdio.h>int main() {// 初始化COMHRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);if (FAILED(hr)) {printf("COM init failed. Error: %08X\n", hr);return 1;}// 创建DOM对象IXMLDOMDocument2* pXMLDoc = NULL;hr = CoCreateInstance(__uuidof(DOMDocument60),NULL,CLSCTX_INPROC_SERVER,__uuidof(IXMLDOMDocument2),(void**)&pXMLDoc);if (FAILED(hr) || !pXMLDoc) {printf("Failed to create DOM. Error: %08X\n", hr);CoUninitialize();return 1;}// 加载XMLVARIANT_BOOL bSuccess = VARIANT_FALSE;hr = pXMLDoc->load(_variant_t(L"example.xml"), &bSuccess);if (FAILED(hr) || bSuccess != VARIANT_TRUE) {printf("Failed to load XML. Error: %08X\n", hr);pXMLDoc->Release();CoUninitialize();return 1;}// 获取根节点IXMLDOMElement* pRoot = NULL;hr = pXMLDoc->get_documentElement(&pRoot);if (FAILED(hr)) {printf("Failed to get root. Error: %08X\n", hr);pXMLDoc->Release();CoUninitialize();return 1;}// 遍历子节点IXMLDOMNodeList* pNodes = NULL;hr = pRoot->get_childNodes(&pNodes);if (FAILED(hr)) {printf("Failed to get child nodes. Error: %08X\n", hr);pRoot->Release();pXMLDoc->Release();CoUninitialize();return 1;}long length = 0;pNodes->get_length(&length);for (long i = 0; i < length; i++) {IXMLDOMNode* pNode = NULL;pNodes->get_item(i, &pNode);BSTR nodeName;pNode->get_nodeName(&nodeName);printf("Node %d: %S\n", i, nodeName);SysFreeString(nodeName);pNode->Release();}// 修改节点属性IXMLDOMElement* pFirstChild = NULL;pNodes->get_item(0, (IXMLDOMNode**)&pFirstChild);hr = pFirstChild->setAttribute(_bstr_t(L"newAttr"), _variant_t(L"newValue"));if (FAILED(hr)) {printf("Failed to set attribute. Error: %08X\n", hr);}// 保存XMLhr = pXMLDoc->save(_variant_t(L"modified.xml"));if (FAILED(hr)) {printf("Failed to save XML. Error: %08X\n", hr);}// 释放资源pFirstChild->Release();pNodes->Release();pRoot->Release();pXMLDoc->Release();CoUninitialize();return 0;
}

演示2

// Windows 头文件,提供基础API支持
#include <windows.h>// MSXML 6.0 接口定义头文件
#include <msxml6.h>// COM 基础功能头文件,包含CoInitialize等函数
#include <objbase.h>// 标准输入输出头文件
#include <stdio.h>// 添加以下头文件
#include <comutil.h>// 添加以下链接库
#pragma comment(lib, "comsuppw.lib")// 链接器指令:自动链接必要的库文件
#pragma comment(lib, "msxml6.lib")  // MSXML 6.0 库
#pragma comment(lib, "ole32.lib")   // COM 基础库int main() {/****************************************************************** 第一部分:COM库初始化和XML文档对象创建*****************************************************************/// 初始化COM库,所有使用COM技术的程序都必须先调用此函数// 参数NULL表示使用默认的线程模型(单线程公寓STA)HRESULT hr = CoInitialize(NULL);if (FAILED(hr)) {printf("错误:COM库初始化失败。错误代码 = 0x%08x\n", hr);return -1;}// 创建XML文档对象指针,初始化为NULLIXMLDOMDocument2* pXMLDoc = NULL;// 使用CoCreateInstance创建MSXML DOM文档对象// 参数说明:// CLSID_DOMDocument60 - MSXML 6.0 DOM文档的类ID// NULL - 不进行聚合// CLSCTX_INPROC_SERVER - 创建进程内服务器// IID_IXMLDOMDocument2 - 请求的接口ID// (void**)&pXMLDoc - 接收接口指针的地址hr = CoCreateInstance(CLSID_DOMDocument60,NULL,CLSCTX_INPROC_SERVER,IID_IXMLDOMDocument2,(void**)&pXMLDoc);// 检查创建是否成功if (FAILED(hr) || pXMLDoc == NULL) {printf("错误:创建DOM文档对象失败。错误代码 = 0x%08x\n", hr);CoUninitialize();  // 释放COM库return -1;}/****************************************************************** 第二部分:设置文档属性*****************************************************************/// 设置异步加载为FALSE(同步加载)// VARIANT_FALSE表示禁用异步加载hr = pXMLDoc->put_async(VARIANT_FALSE);// 设置验证文档结构(如果文档有DTD或Schema)// VARIANT_TRUE表示开启验证hr = pXMLDoc->put_validateOnParse(VARIANT_TRUE);// 设置不解析外部资源(如外部DTD)// VARIANT_FALSE表示不解析外部资源hr = pXMLDoc->put_resolveExternals(VARIANT_FALSE);// 设置保留空白字符// VARIANT_TRUE表示保留空白字符(如缩进、换行等)hr = pXMLDoc->put_preserveWhiteSpace(VARIANT_TRUE);/****************************************************************** 第三部分:创建和加载XML文档*****************************************************************/// 创建一个包含XML内容的BSTR字符串// BSTR是COM中使用的字符串类型,以长度前缀和null结尾BSTR bstrXML = SysAllocString(L"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"L"<bookstore>\n"L"  <book category=\"cooking\">\n"L"    <title lang=\"en\">Everyday Italian</title>\n"L"    <author>Giada De Laurentiis</author>\n"L"    <year>2005</year>\n"L"    <price>30.00</price>\n"L"  </book>\n"L"  <book category=\"children\">\n"L"    <title lang=\"en\">Harry Potter</title>\n"L"    <author>J.K. Rowling</author>\n"L"    <year>2005</year>\n"L"    <price>29.99</price>\n"L"  </book>\n"L"  <book category=\"web\">\n"L"    <title lang=\"en\">Learning XML</title>\n"L"    <author>Erik T. Ray</author>\n"L"    <year>2003</year>\n"L"    <price>39.95</price>\n"L"  </book>\n"L"</bookstore>");// 用于接收加载是否成功的变量VARIANT_BOOL vbIsSuccessful;// 将XML字符串加载到文档对象中hr = pXMLDoc->loadXML(bstrXML, &vbIsSuccessful);// 释放BSTR内存(COM编程中必须手动释放分配的内存)SysFreeString(bstrXML);// 检查XML加载是否成功if (FAILED(hr) || vbIsSuccessful != VARIANT_TRUE) {printf("错误:加载XML字符串失败。\n");// 获取解析错误对象IXMLDOMParseError* pXMLError = NULL;BSTR bstrError = NULL;// 获取解析错误信息hr = pXMLDoc->get_parseError(&pXMLError);if (SUCCEEDED(hr)) {// 获取错误原因描述pXMLError->get_reason(&bstrError);printf("错误原因: %S\n", bstrError);// 释放错误描述字符串SysFreeString(bstrError);// 释放错误对象pXMLError->Release();}// 清理资源pXMLDoc->Release();CoUninitialize();return -1;}/****************************************************************** 第四部分:演示从文件加载XML(补充功能)*****************************************************************/// 创建另一个XML文档对象用于演示文件加载IXMLDOMDocument2* pXMLDocFromFile = NULL;hr = CoCreateInstance(CLSID_DOMDocument60, NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument2, (void**)&pXMLDocFromFile);if (SUCCEEDED(hr) && pXMLDocFromFile != NULL) {// 设置文档属性(同上)pXMLDocFromFile->put_async(VARIANT_FALSE);pXMLDocFromFile->put_validateOnParse(VARIANT_TRUE);// 创建VARIANT变量来指定文件名VARIANT varFileName;VariantInit(&varFileName);  // 初始化VARIANTvarFileName.vt = VT_BSTR;   // 设置类型为BSTR// 分配文件名(假设当前目录下有books.xml文件)varFileName.bstrVal = SysAllocString(L"books.xml");// 从文件加载XMLhr = pXMLDocFromFile->load(varFileName, &vbIsSuccessful);// 清理VARIANTVariantClear(&varFileName);if (SUCCEEDED(hr) && vbIsSuccessful == VARIANT_TRUE) {printf("成功从文件加载XML文档。\n");// 这里可以添加对加载文档的操作...} else {printf("警告:从文件加载XML失败,可能文件不存在。\n");}// 释放文档对象pXMLDocFromFile->Release();}/****************************************************************** 第五部分:遍历XML文档*****************************************************************/// 获取文档根元素IXMLDOMElement* pRootElem = NULL;hr = pXMLDoc->get_documentElement(&pRootElem);if (SUCCEEDED(hr) && pRootElem != NULL) {// 获取根元素名称BSTR bstrRootName;hr = pRootElem->get_nodeName(&bstrRootName);if (SUCCEEDED(hr)) {printf("根元素名称: %S\n", bstrRootName);SysFreeString(bstrRootName);}/****************************************************************** 演示创建处理指令(补充功能)*****************************************************************/// 创建处理指令节点IXMLDOMProcessingInstruction* pPI = NULL;BSTR bstrTarget = SysAllocString(L"xml-stylesheet");BSTR bstrData = SysAllocString(L"type=\"text/xsl\" href=\"style.xsl\"");hr = pXMLDoc->createProcessingInstruction(bstrTarget, bstrData, &pPI);if (SUCCEEDED(hr) && pPI != NULL) {// 将处理指令插入到文档开头IXMLDOMNode* pInsertedNode = NULL;hr = pXMLDoc->insertBefore(pPI, _variant_t(pRootElem), &pInsertedNode);if (SUCCEEDED(hr)) {printf("成功添加处理指令。\n");pInsertedNode->Release();}pPI->Release();}SysFreeString(bstrTarget);SysFreeString(bstrData);/****************************************************************** 演示创建注释(补充功能)*****************************************************************/// 创建注释节点IXMLDOMComment* pComment = NULL;BSTR bstrComment = SysAllocString(L"这是一个示例XML文档");hr = pXMLDoc->createComment(bstrComment, &pComment);if (SUCCEEDED(hr) && pComment != NULL) {// 将注释插入到根元素之前IXMLDOMNode* pInsertedComment = NULL;hr = pXMLDoc->insertBefore(pComment, _variant_t(pRootElem), &pInsertedComment);if (SUCCEEDED(hr)) {printf("成功添加注释节点。\n");pInsertedComment->Release();}pComment->Release();}SysFreeString(bstrComment);/****************************************************************** 遍历book节点*****************************************************************/// 获取所有book元素IXMLDOMNodeList* pBooks = NULL;BSTR bstrTagName = SysAllocString(L"book");hr = pRootElem->getElementsByTagName(bstrTagName, &pBooks);SysFreeString(bstrTagName);if (SUCCEEDED(hr) && pBooks != NULL) {// 获取book元素数量long bookCount;pBooks->get_length(&bookCount);printf("找到 %d 本书\n", bookCount);// 遍历每本书for (long i = 0; i < bookCount; i++) {IXMLDOMNode* pBook = NULL;hr = pBooks->get_item(i, &pBook);if (SUCCEEDED(hr) && pBook != NULL) {// 获取整本书的XML内容BSTR bstrBookXML;pBook->get_xml(&bstrBookXML);printf("\n第 %d 本书:\n%S\n", i + 1, bstrBookXML);SysFreeString(bstrBookXML);// 获取book元素的属性IXMLDOMNamedNodeMap* pAttrs = NULL;pBook->get_attributes(&pAttrs);if (pAttrs != NULL) {// 获取category属性IXMLDOMNode* pCategoryAttr = NULL;BSTR bstrAttrName = SysAllocString(L"category");hr = pAttrs->getNamedItem(bstrAttrName, &pCategoryAttr);SysFreeString(bstrAttrName);if (SUCCEEDED(hr) && pCategoryAttr != NULL) {VARIANT varValue;VariantInit(&varValue);// 获取属性值pCategoryAttr->get_nodeValue(&varValue);printf("  类别: %S\n", varValue.bstrVal);// 清理VARIANTVariantClear(&varValue);pCategoryAttr->Release();}pAttrs->Release();}/****************************************************************** 演示克隆节点(补充功能)*****************************************************************/// 克隆当前book节点(深拷贝,包括所有子节点)IXMLDOMNode* pClonedBook = NULL;hr = pBook->cloneNode(VARIANT_TRUE, &pClonedBook);if (SUCCEEDED(hr) && pClonedBook != NULL) {// 可以在此处操作克隆的节点...printf("  成功克隆本书节点。\n");pClonedBook->Release();}/****************************************************************** 遍历子节点*****************************************************************/IXMLDOMNodeList* pChildNodes = NULL;pBook->get_childNodes(&pChildNodes);if (pChildNodes != NULL) {long childCount;pChildNodes->get_length(&childCount);for (long j = 0; j < childCount; j++) {IXMLDOMNode* pChild = NULL;hr = pChildNodes->get_item(j, &pChild);if (SUCCEEDED(hr) && pChild != NULL) {// 获取子节点名称BSTR bstrChildName;pChild->get_nodeName(&bstrChildName);// 特别处理price节点if (wcscmp(bstrChildName, L"price") == 0) {BSTR bstrPrice;pChild->get_text(&bstrPrice);printf("  价格: %S\n", bstrPrice);SysFreeString(bstrPrice);}SysFreeString(bstrChildName);pChild->Release();}}pChildNodes->Release();}pBook->Release();}}pBooks->Release();}/****************************************************************** 演示删除节点(补充功能)*****************************************************************/// 查找要删除的节点(例如第一本书)IXMLDOMNode* pBookToRemove = NULL;BSTR bstrXPathRemove = SysAllocString(L"//book[1]");hr = pXMLDoc->selectSingleNode(bstrXPathRemove, &pBookToRemove);SysFreeString(bstrXPathRemove);if (SUCCEEDED(hr) && pBookToRemove != NULL) {// 从父节点中删除子节点IXMLDOMNode* pRemovedNode = NULL;hr = pRootElem->removeChild(pBookToRemove, &pRemovedNode);if (SUCCEEDED(hr)) {printf("\n成功删除第一本书。\n");pRemovedNode->Release();}pBookToRemove->Release();}pRootElem->Release();}/****************************************************************** 第六部分:执行XPath查询*****************************************************************/// 查找价格大于35的书BSTR bstrXPath = SysAllocString(L"//book[price>35.00]");IXMLDOMNodeList* pExpensiveBooks = NULL;hr = pXMLDoc->selectNodes(bstrXPath, &pExpensiveBooks);SysFreeString(bstrXPath);if (SUCCEEDED(hr) && pExpensiveBooks != NULL) {long expensiveCount;pExpensiveBooks->get_length(&expensiveCount);printf("\n找到 %d 本价格高于35.00的书\n", expensiveCount);// 遍历查询结果for (long i = 0; i < expensiveCount; i++) {IXMLDOMNode* pBook = NULL;hr = pExpensiveBooks->get_item(i, &pBook);if (SUCCEEDED(hr) && pBook != NULL) {// 在每本书中查找title节点BSTR bstrTitleXPath = SysAllocString(L"title");IXMLDOMNode* pTitle = NULL;// 注意:这里需要将pBook转换为IXMLDOMElement接口hr = ((IXMLDOMElement*)pBook)->selectSingleNode(bstrTitleXPath, &pTitle);SysFreeString(bstrTitleXPath);if (SUCCEEDED(hr) && pTitle != NULL) {BSTR bstrTitle;pTitle->get_text(&bstrTitle);printf("  高价书标题: %S\n", bstrTitle);SysFreeString(bstrTitle);pTitle->Release();}pBook->Release();}}pExpensiveBooks->Release();}/****************************************************************** 第七部分:修改XML内容*****************************************************************/// 查找所有book节点BSTR bstrAllBooksXPath = SysAllocString(L"//book");IXMLDOMNodeList* pAllBooks = NULL;hr = pXMLDoc->selectNodes(bstrAllBooksXPath, &pAllBooks);SysFreeString(bstrAllBooksXPath);if (SUCCEEDED(hr) && pAllBooks != NULL) {long bookCount;pAllBooks->get_length(&bookCount);for (long i = 0; i < bookCount; i++) {IXMLDOMNode* pBook = NULL;hr = pAllBooks->get_item(i, &pBook);if (SUCCEEDED(hr) && pBook != NULL) {// 创建discount元素IXMLDOMElement* pDiscountElem = NULL;BSTR bstrDiscountTag = SysAllocString(L"discount");hr = pXMLDoc->createElement(bstrDiscountTag, &pDiscountElem);SysFreeString(bstrDiscountTag);if (SUCCEEDED(hr) && pDiscountElem != NULL) {// 设置discount元素的文本内容BSTR bstrDiscountValue = SysAllocString(L"10%");hr = pDiscountElem->put_text(bstrDiscountValue);SysFreeString(bstrDiscountValue);// 将新元素添加到book节点IXMLDOMNode* pInsertedNode = NULL;hr = pBook->appendChild(pDiscountElem, &pInsertedNode);if (SUCCEEDED(hr) && pInsertedNode != NULL) {pInsertedNode->Release();}pDiscountElem->Release();}/****************************************************************** 演示替换节点(补充功能)*****************************************************************/// 查找year节点BSTR bstrYearPath = SysAllocString(L"year");IXMLDOMNode* pYearNode = NULL;hr = ((IXMLDOMElement*)pBook)->selectSingleNode(bstrYearPath, &pYearNode);SysFreeString(bstrYearPath);if (SUCCEEDED(hr) && pYearNode != NULL) {// 创建新的year节点IXMLDOMElement* pNewYearElem = NULL;BSTR bstrYearTag = SysAllocString(L"year");hr = pXMLDoc->createElement(bstrYearTag, &pNewYearElem);SysFreeString(bstrYearTag);if (SUCCEEDED(hr) && pNewYearElem != NULL) {// 设置新的年份值(原年份+1)BSTR bstrOldYear;pYearNode->get_text(&bstrOldYear);int year = _wtoi(bstrOldYear) + 1;wchar_t newYear[10];swprintf(newYear, 10, L"%d", year);BSTR bstrNewYear = SysAllocString(newYear);pNewYearElem->put_text(bstrNewYear);SysFreeString(bstrNewYear);SysFreeString(bstrOldYear);// 替换节点IXMLDOMNode* pReplacedNode = NULL;hr = pBook->replaceChild(pNewYearElem, pYearNode, &pReplacedNode);if (SUCCEEDED(hr)) {printf("  成功更新第%d本书的出版年份。\n", i+1);pReplacedNode->Release();}pNewYearElem->Release();}pYearNode->Release();}pBook->Release();}}pAllBooks->Release();}/****************************************************************** 第八部分:保存修改后的XML*****************************************************************/// 创建VARIANT变量来指定输出文件名VARIANT varOutputFile;VariantInit(&varOutputFile);  // 初始化VARIANTvarOutputFile.vt = VT_BSTR;   // 设置类型为BSTRvarOutputFile.bstrVal = SysAllocString(L"modified_books.xml");// 保存XML文档到文件hr = pXMLDoc->save(varOutputFile);if (FAILED(hr)) {printf("错误:保存修改后的XML文件失败。\n");} else {printf("\n修改后的XML已保存到 modified_books.xml\n");}// 清理VARIANT变量VariantClear(&varOutputFile);/****************************************************************** 第九部分:清理资源*****************************************************************/// 释放XML文档对象pXMLDoc->Release();// 反初始化COM库CoUninitialize();// 暂停控制台窗口(方便查看输出)system("pause");return 0;
}

8. 总结

本文详细介绍了如何在C++中使用MSXML进行XML解析、遍历、修改和保存,并提供了完整的代码示例和逐行注释。关键点包括:

  1. 初始化COM环境CoInitializeEx)。
  2. 创建MSXML DOM对象CoCreateInstance)。
  3. 加载XML文件load)。
  4. 遍历和修改节点get_childNodes, setAttribute)。
  5. 保存XMLsave)。

通过本教程,可以快速掌握MSXML的基本用法,并应用于实际项目中。


http://www.mrgr.cn/news/98261.html

相关文章:

  • C语言十大经典数学应用
  • 考研单词笔记 2025.04.13
  • 【甲子光年】DeepSeek开启AI算法变革元年
  • Go:方法
  • 【随身wifi】青龙面板保姆级教程
  • C语言的发展史
  • cursor+高德MCP:制作一份旅游攻略
  • 2025蓝桥杯C++ A组省赛 题解
  • 【嵌入式人工智能产品开发实战】(十九)—— 政安晨:小智AI嵌入式终端代码解读:【A】应用入口
  • 【深度学习与大模型基础】第10章-期望、方差和协方差
  • 【NLP】18. Encoder 和 Decoder
  • vue项目使用html2canvas和jspdf将页面导出成PDF文件
  • Restful风格接口开发
  • C语言斐波那契数列的多样实现
  • OpenHarmony5.0.2 USB摄像头适配
  • Java面向对象核心:多态、抽象类与接口实战解析
  • 基于51单片机的正负5V数字电压表( proteus仿真+程序+设计报告+讲解视频)
  • c语言 open函数
  • C语言中冒泡排序和快速排序的区别
  • 02核心-EffectSpec,EffectContext