图解数据结构】 二叉树遍历

目录 史上最最靠谱,又双叒叒简单的基于MSXML的XML解析指南 流程设计 xml信息有哪几种读取形式(xml文件或wchar) 如何选取节点,and取节点属性有哪些方法? IXMLDOMNode与IXMLDOMElement接口有何联系、区别 节点如果是数组,怎么操作? 如何为属性插入属性 字符串的转换与输出 主要代码 史上最最靠谱,又双叒叒简单的基于MSXML的XML解析指南 最近做C++相关的项目,遇到同时使用COM和MSXML来解析XML文件中信息的问题,这类问题如果做MFC开发也会经常用到。 在网上搜了一整圈,确实很难找到可用的code,总算自己研究出高效而简单的方法,借此机会总结一下,并分享给大家。 附 VS Project镜像: SimpleParser4MSXML-cpp: C++语言写的MSXML的简单使用示例, COM 和 MFC 开发中比较常用。 https://github.com/yanglr/SimpleParser4MSXML-cpp 点击”Raw”可看到源码,欢迎fork或star~ 首先简要列举一下MSXML技术的基本特点。 基于 COM 的技术,用于处理 Windows 操作系统随附的 XML。 MSXML 提供 DOM 本机实现,同时支持 XPath 和 XSLT。 包含 SAX2 基于事件的分析器。 流程设计 首先简要介绍一下大概流程: 初始化COM 创建一个IDOMDocument对象xmlDoc,使用xmlDoc -> load() 或 loadXML()方法读入 XML源 调用selectNodes()或者selectSingleNode()函数,选取指定的节点对象。 通过IXMLDOMNode对象的属性和方法读取节点对象的内容。 通过IXMLDOMNode对象的属性和方法设置节点对象的内容。 通过调用xmlDoc -> save()保存XML文件。 关闭COM 需要解决的问题: xml信息有哪几种读取形式(xml文件或wchar) 如何选取节点,and取节点属性有哪些方法? IXMLDOMNode 与 IXMLDOMElement 接口有什么联系和区别? 节点如果是数组,怎么操作? 如何为属性插入属性 字符串的转换 xml信息有哪几种读取形式(xml文件或wchar) xml文件 从文件中导入xml内容,使用url或filePath VARIANT_BOOL bSuccess = false; HRESULT hr = iXMLDoc->load(CComVariant(L"./test.xml"), &bSuccess); // 此处的L可以省略 当已变量方式传人filePath时,需要使用c_str()函数转换一下,代码如下: VARIANT_BOOL bSuccess = false; filePath = "./test.xml"; HRESULT hr = iXMLDoc->load(CComVariant(filePath.c_str()), &bSuccess); 已以字符串格式读入的xml完整代码 先定义一个BSTR常量 const wchar_t *src = L"" L"\r\n" L"\r\n" L" Hey\r\n" L" \r\n" L" \r\n" L" \r\n" L" \r\n" L" \r\n" L"\r\n"; 然后从BSTR`导入xml内容: VARIANT_BOOL bSuccess = false; iXMLDoc->loadXML(CComBSTR(src), &bSuccess); 注: BSTR字符串是用于COM组件对象模型的字符串格式, 字符串以表示字符串长度的4字节整数开始, 然后跟上UTF-16编码的wchar_t字符串(包括\0结束标志)。BSTR类型的变量是一个指针, 指向字符串的第一个字符处。 如何选取节点,and取节点属性有哪些方法? 搜索节点名字 CComBSTR sstrRoot(L"root"); // sstrRoot("root"); CComPtr rootNode; HRESULT hr = iXMLDoc->selectSingleNode(sstrRoot, &rootNode); CComPtr textNode; hr = rootNode->selectSingleNode(CComBSTR(L"text"), &textNode); // 搜索第一个"text"节点 IXMLDOMNode与IXMLDOMElement接口有何联系、区别 IXMLDOMElement接口继承于IXMLDOMNode接口,但除了从IXMLDOMNode接口继承的方法之外,IXMLDOMElement接口还向外暴露以下方法: 方法 说明 get_tagName 检索元素名称(在tag之间的文本)。 getAttribute 检索所指定名字的属性的值。 getAttributeNode 检索所指定名字的属性的节点 getElementsByTagName 检索与提供的名称匹配的所有子元素的列表。 removeAttribute 移动或替换给定名称的属性 removeAttributeNode 从这个元素中移除指定的属性 setAttribute 为给定名称的属性设置值 setAttributeNode 在此元素上添加或替换提供的属性节点。 节点如果是数组,怎么操作? 先使用get_childNodes函数获得子节点列表,然后遍历之用get_item依次取出每一项进行处理。 CComPtr pRootElement; CComPtr pNodeList; pRootElement->get_childNodes(&pNodeList); // Child node list long nLen; pNodeList->get_length(&nLen); // Child node list for (long index = 0; i != nLen; ++index) // Traverse { CComPtr pCurNode; hr = pNodeList->get_item(index, &pCurNode); do(); // 此处可做任何你想做的事情 } 如何为属性插入属性 使用Element->setAttribute()即可,具体如下: CComPtr imageElement; xmlDocData->createElement(CComBSTR(L"Image"), &imageElement); // 创建节点"Image" imageElement->setAttribute(CComBSTR(L"Type"), CComVariant(CComBSTR(imageType.c_str()))); // 添加属性"Type" 字符串的转换与输出 直接使用printf函数+“%ls”或wprintf函数+“%s”打印BSTR类字符串 CComBSTR ssName; printf("Node name:%ls\n", ssName); // 用%ls打印BSTR字符串内容 SysFreeString(ssName); // 用完字符串后必须释放 或 CComBSTR ssName; wprintf(L"Node name:%s\n", ssName); // 这里的L不能省略 SysFreeString(ssName); 将CComBSTR类字符串的内容复制到wstring中,然后使用wcout输出 CComBSTR ssName; wstring bstrText(ssName); wcout << bstrText << endl; 或 先使用将bstr转为std::wstring,然后wcout std::wstring wstringName(ssName, SysStringLen(ssName)); wcout << wstringName << endl; 先将CComBSTR类字符串强转为LPCTSTR类型后,然后使用wcout输出 对CStringW类字符串而言,这已经是一种比较简单的方式了。 CComBSTR ssName; CString cstring(ssName); wcout << (LPCTSTR)cstring << endl; 将CComBSTR类字符串的内容复制到CW2A类字符串(多字节字符串)中,然后使用wcout输出 CComBSTR ssName; CW2A printstr(ssName); cout << printstr << endl; 先使用宏W2A将bstr转为std::string,然后cout USES_CONVERSION; std::string stringName = std::string(W2A(ssName)); cout << stringName << endl; 主要代码 #include // 含有 MSXML最新版 #include #include "atlstr.h" // 含有CString, CStringW和CW2A #include // 包含wcout函数 #include // 包含 c_str()函数, wcout #include "comutil.h" // 包含_bstr_t using namespace std; const wchar_t *src = L"" L"\r\n" L"\r\n" L" Hey\r\n" L" \r\n" L" \r\n" L" \r\n" L" \r\n" L" \r\n" L"\r\n"; int main() { CoInitialize(NULL); // Initialize COM CComPtr iXMLDoc; // Or use CComPtr, CComPtr try { HRESULT hr = iXMLDoc.CoCreateInstance(__uuidof(DOMDocument)); // iXMLDoc.CoCreateInstance(__uuidof(DOMDocument60)); // Load the file. VARIANT_BOOL bSuccess = false; // Load it from a url/filename... hr = iXMLDoc->load(CComVariant(L"./test.xml"), &bSuccess); // filePath = "./test.xml"; // hr = iXMLDoc->load(CComVariant(filePath.c_str()), &bSuccess); // or from a BSTR... // iXMLDoc->loadXML(CComBSTR(src), &bSuccess); // Get a smart pointer (sp) to the root CComPtr pRootElement; hr = iXMLDoc->get_documentElement(&pRootElement); // Root elements // Get Attribute value of the note "root" CComBSTR ssDesc("desc"); CComVariant deVal(VT_EMPTY); hr = pRootElement->getAttribute(ssDesc, &deVal); CComBSTR sstrRoot(L"root"); // sstrRoot("root"); CComPtr rootNode; hr = iXMLDoc->selectSingleNode(sstrRoot, &rootNode); // Search "root" CComBSTR rootText; hr = rootNode->get_text(&rootText); if (SUCCEEDED(hr)) { wstring bstrText(rootText); wcout << "Text of root: " << bstrText << endl; } CComPtr descAttribute; hr = rootNode->selectSingleNode(CComBSTR("@desc"), &descAttribute); // Atrribute需要用@, 而各个节点不能使用@作为前缀来搜索 CComBSTR descVal; hr = descAttribute->get_text(&descVal); if (SUCCEEDED(hr)) { wstring bstrText(descVal); wcout << "Desc Attribute: " << bstrText << endl; } if (!FAILED(hr)) { wstring strVal; if (deVal.vt == VT_BSTR) strVal = deVal.bstrVal; wcout << "desc: " << strVal << endl; } CComPtr pNodeList; pRootElement->get_childNodes(&pNodeList); // Child node list long nLen; pNodeList->get_length(&nLen); // Child node list for (long i = 0; i != nLen; ++i) // Traverse { CComPtr pNode; hr = pNodeList->get_item(i, &pNode); CComBSTR ssName; CComVariant val(VT_EMPTY); hr = pNode->get_nodeName(&ssName); if (SUCCEEDED(hr)) { wstring bstrText(ssName); wcout << "Name of node " << (i + 1) << ": " << bstrText << endl; CString cstring(ssName); // To display a CStringW correctly, use wcout and cast cstring to (LPCTSTR), an easier way to display wide character strings. wcout << (LPCTSTR)cstring << endl; // CW2A converts the string in ccombstr to a multi-byte string in printstr, used for display output. CW2A printstr(ssName); cout << printstr << endl; } } /// Add(Append) node CComPtr& xmlDocData(iXMLDoc); CComPtr imageElement; CComPtr newImageNode; string imageType = "jpeg"; char buffer[MAX_PATH]; GetCurrentDirectory(MAX_PATH, buffer); // Get Current Directory string path(buffer); // Copy content of char*, generate a string string imagePath = path + "\\com.jpg"; xmlDocData->createElement(CComBSTR(L"Image"), &imageElement); imageElement->setAttribute(CComBSTR(L"Type"), CComVariant(CComBSTR(imageType.c_str()))); // 为当前节点添加属性 imageElement->setAttribute(CComBSTR(L"FileName"), CComVariant(CComBSTR(imagePath.c_str()))); rootNode->appendChild(imageElement, &newImageNode); /// Remove "text" node under "root" node CComPtr xmlOldNode; CComPtr textNode; hr = rootNode->selectSingleNode(CComBSTR(L"text"), &textNode); // Search "text" node hr = rootNode->removeChild(textNode, &xmlOldNode); /// Update XML hr = iXMLDoc->save(CComVariant("updated.xml")); } catch (char* pStrErr) { // Some error... std::cout << pStrErr << std::endl << std::endl; } // catch catch (...) { // Unknown error... std::cout << "Unknown error..." << std::endl << std::endl; } // Release() - that gets done automatically, also can manually do for each opened node or elements. // iXMLDoc.Release(); // Stop COM CoUninitialize(); system("pause"); return 0; } 运行结果: run Result 运行完,得到的update.xml内容为: https://raw.githubusercontent.com/yanglr/SimpleParser4MSXML-cpp/master/msxmlDemo/updated.xml 参考资料: IXMLDOMElement接口 Using the MSXML Parser MFC C++ XML Parse - Using MSXML 如何:各种字符串类型之间转换 | Microsoft Docs 本文原载于本人的CSDN博客: 史上最最靠谱,又双叒叒(ruò,zhuó)简单的基于MSXML的XML解析指南-C++ - Bravo Yeung-羊较瘦之自留地 分类: C++开发,微软系列技术https://www.cnblogs.com/enjoy233/p/10298236.htm
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信