史上最最靠谱,又双叒叒简单的基于MSXML的XML解析指南
目录
史上最最靠谱,又双叒叒简单的基于MSXML的XML解析指南最近做C++相关的项目,遇到同时使用COM和MSXML来解析XML文件中信息的问题,这类问题如果做MFC开发也会经常用到。 附 VS Project镜像:
流程设计首先简要介绍一下大概流程:
需要解决的问题:
xml信息有哪几种读取形式(xml文件或wchar)
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);
先定义一个 const wchar_t *src = L"" L"<?xml version="1.0" encoding="utf-16"?>rn" L"<root desc="Great">rn" L" <text>Hey</text>rn" L" <layouts>rn" L" <lay index="15" bold="true"/>rn" L" <layoff index="12"/>rn" L" <layin index="17"/>rn" L" </layouts>rn" L"</root>rn"; 然后从 VARIANT_BOOL bSuccess = false; iXMLDoc->loadXML(CComBSTR(src),&bSuccess); 注: BSTR字符串是用于COM组件对象模型的字符串格式,字符串以表示字符串长度的4字节整数开始,然后跟上UTF-16编码的wchar_t字符串(包括 结束标志)。BSTR类型的变量是一个指针,指向字符串的第一个字符处。 如何选取节点,and取节点属性有哪些方法?
CComBSTR sstrRoot(L"root"); // sstrRoot("root"); CComPtr<IXMLDOMNode> rootNode; HRESULT hr = iXMLDoc->selectSingleNode(sstrRoot,&rootNode); CComPtr<IXMLDOMNode> textNode; hr = rootNode->selectSingleNode(CComBSTR(L"text"),&textNode); // 搜索第一个"text"节点 IXMLDOMNode与IXMLDOMElement接口有何联系、区别IXMLDOMElement接口继承于IXMLDOMNode接口,但除了从IXMLDOMNode接口继承的方法之外,IXMLDOMElement接口还向外暴露以下方法:
节点如果是数组,怎么操作?先使用get_childNodes函数获得子节点列表,然后遍历之用get_item依次取出每一项进行处理。 CComPtr<IXMLDOMElement> pRootElement; CComPtr<IXMLDOMNodeList> 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<IXMLDOMNode> pCurNode; hr = pNodeList->get_item(index,&pCurNode); do(); // 此处可做任何你想做的事情 } 如何为属性插入属性使用Element->setAttribute()即可,具体如下: CComPtr<IXMLDOMElement> imageElement; xmlDocData->createElement(CComBSTR(L"Image"),&imageElement); // 创建节点"Image" imageElement->setAttribute(CComBSTR(L"Type"),CComVariant(CComBSTR(imageType.c_str()))); // 添加属性"Type" 字符串的转换与输出
CComBSTR ssName; printf("Node name:%lsn",ssName); // 用%ls打印BSTR字符串内容 SysFreeString(ssName); // 用完字符串后必须释放 或 CComBSTR ssName; wprintf(L"Node name:%sn",ssName); // 这里的L不能省略 SysFreeString(ssName);
CComBSTR ssName; wstring bstrText(ssName); wcout << bstrText << endl; 或
std::wstring wstringName(ssName,SysStringLen(ssName)); wcout << wstringName << endl;
CComBSTR ssName; CString cstring(ssName); wcout << (LPCTSTR)cstring << endl;
CComBSTR ssName; CW2A printstr(ssName); cout << printstr << endl;
USES_CONVERSION; std::string stringName = std::string(W2A(ssName)); cout << stringName << endl; 主要代码#include <msxml6.h> // 含有 MSXML最新版 #include <atlbase.h> #include "atlstr.h" // 含有CString,CStringW和CW2A #include <iostream> // 包含wcout函数 #include <string> // 包含 c_str()函数,wcout #include "comutil.h" // 包含_bstr_t using namespace std; const wchar_t *src = L"" L"<?xml version="1.0" encoding="utf-16"?>rn" L"<root desc="Great">rn" L" <text>Hey</text>rn" L" <layouts>rn" L" <lay index="15" bold="true"/>rn" L" <layoff index="12"/>rn" L" <layin index="17"/>rn" L" </layouts>rn" L"</root>rn"; int main() { CoInitialize(NULL); // Initialize COM CComPtr<IXMLDOMDocument> iXMLDoc; // Or use CComPtr<IXMLDOMDocument2>,CComPtr<IXMLDOMDocument3> 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<IXMLDOMElement> 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<IXMLDOMNode> 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<IXMLDOMNode> 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<IXMLDOMNodeList> 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<IXMLDOMNode> 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<IXMLDOMDocument>& xmlDocData(iXMLDoc); CComPtr<IXMLDOMElement> imageElement; CComPtr<IXMLDOMNode> 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<IXMLDOMNode> xmlOldNode; CComPtr<IXMLDOMNode> 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; } 运行结果: 运行完,得到的update.xml内容为:
本文原载于本人的CSDN博客: (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |