C++ XML解析示例

在现代软件开发中,XML文件被广泛用于数据交换和配置管理。C++作为一种强大的编程语言,提供了多种方式来解析XML文件。本文将介绍如何使用C++和MSXML库来解析XML文档,并展示如何使用ATL智能指针来简化内存管理。

环境设置

在开始之前,需要根据所使用的开发环境进行相应的设置。这里将介绍如何在Visual Studio .NET、BorlandC++Builder以及嵌入式Visual C++ (EVC)中进行设置。

Visual Studio .NET自带了所需的库和环境,因此无需额外设置。

在BorlandC++Builder中,需要在项目选项的目录中添加ATL的头文件路径。

对于EVC,需要下载并包含一个免费的STL端口,该端口由Giuseppe Govi制作。

包含的头文件

C++代码中,需要包含以下头文件:

#include <windows.h> #include <msxml.h> #include <objsafe.h> #include <objbase.h> #include <atlbase.h>

为了处理警告,可以使用以下代码:

#pragma warning( push ) #pragma warning( disable: 4018 4786) #include <string> #pragma warning( pop )

使用命名空间std以简化代码:

using namespace std;

初始化COM库

在WinMain的开始处初始化COM库,并在结束处进行反初始化:

CoInitializeEx(NULL, COINIT_MULTITHREADED); // ... CoUninitialize();

对于桌面Win32编译,可以使用CoInitialize(NULL),因为它在Win95上也能工作,不需要定义_WIN32_WINNT。但是它在PocketPC上不可用。

XML文档的加载

使用ATL的智能指针来避免手动调用Release()。以下代码展示了如何加载XML文档:

CComPtr<IXMLDOMDocument> iXMLDoc; iXMLDoc.CoCreateInstance(__uuidof(DOMDocument)); #ifdef UNDER_CE iXMLDoc->put_async(VARIANT_FALSE); CComQIPtr<IObjectSafety, &IID_IObjectSafety> isafe(iXMLDoc); if (isafe) { DWORD dwSupported, dwEnabled; isafe->GetInterfaceSafetyOptions(IID_IXMLDOMDocument, &dwSupported, &dwEnabled); isafe->SetInterfaceSafetyOptions(IID_IXMLDOMDocument, dwSupported, 0); } #endif VARIANT_BOOL bSuccess = false; iXMLDoc->load(CComVariant(url), &bSuccess);

如果需要从BSTR加载,可以使用以下代码:

iXMLDoc->loadXML(CComBSTR(s), &bSuccess);

获取根元素:

CComPtr<IXMLDOMElement> iRootElm; iXMLDoc->get_documentElement(&iRootElm);

访问和迭代元素

为了简化元素的访问和迭代,可以编写一个辅助类TElem。以下是一个示例XML文档:

<?xml version="1.0" encoding="utf-16" ?> <root desc="Simple Prog"> <text>Hello World</text> <layouts> <lay pos="15" bold="true" /> <layoff pos="12" /> <layin pos="17" /> </layouts> </root>

以下是如何使用TElem类:

TElem eroot(iRootElm); wstring desc = eroot.attr(L"desc"); TElem etext = eroot.subnode(L"text"); wstring s = etext.val(); s = eroot.subval(L"text"); TElem elays = eroot.subnode(L"layouts"); for (TElem e = elays.begin(); e != elays.end(); e++) { int pos = e.attrInt(L"pos", -1); bool bold = e.attrBool(L"bold", false); wstring id = e.name(); }

TElem类的源代码

struct TElem { CComPtr<IXMLDOMElement> elem; CComPtr<IXMLDOMNodeList> nlist; int pos; long clen; TElem() : elem(0), nlist(0), pos(-1), clen(0) {} TElem(int _clen) : elem(0), nlist(0), pos(-1), clen(_clen) {} TElem(CComPtr<IXMLDOMElement> _elem) : elem(_elem), nlist(0), pos(-1), clen(0) { get(); } TElem(CComPtr<IXMLDOMNodeList> _nlist) : elem(0), nlist(_nlist), pos(0), clen(0) { get(); } void get() { if (pos != -1) { elem = 0; CComPtr<IXMLDOMNode> inode; nlist->get_item(pos, &inode); if (inode == 0) return; DOMNodeType type; inode->get_nodeType(&type); if (type != NODE_ELEMENT) return; CComQIPtr<IXMLDOMElement> e(inode); elem = e; } clen = 0; if (elem != 0) { CComPtr<IXMLDOMNodeList> iNodeList; elem->get_childNodes(&iNodeList); iNodeList->get_length(&clen); } } wstring name() const { if (!elem) return L""; CComBSTR bn; elem->get_tagName(&bn); return wstring(bn); } wstring attr(const wstring name) const { if (!elem) return L""; CComBSTR bname(name.c_str()); CComVariant val(VT_EMPTY); elem->getAttribute(bname, &val); if (val.vt == VT_BSTR) return val.bstrVal; return L""; } bool attrBool(const wstring name, bool def) const { wstring a = attr(name); if (a == L"true" || a == L"TRUE") return true; else if (a == L"false" || a == L"FALSE") return false; else return def; } int attrInt(const wstring name, int def) const { wstring a = attr(name); int i, res = swscanf(a.c_str(), L"%i", &i); if (res == 1) return i; else return def; } wstring val() const { if (!elem) return L""; CComVariant val(VT_EMPTY); elem->get_nodeTypedValue(&val); if (val.vt == VT_BSTR) return val.bstrVal; return L""; } TElem subnode(const wstring name) const { if (!elem) return TElem(); for (TElem c = begin(); c != end(); c++) { if (c.name() == name) return c; } return TElem(); } wstring subval(const wstring name) const { if (!elem) return L""; TElem c = subnode(name); return c.val(); } TElem begin() const { if (!elem) return TElem(); CComPtr<IXMLDOMNodeList> iNodeList; elem->get_childNodes(&iNodeList); return TElem(iNodeList); } TElem end() const { return TElem(clen); } TElem operator++(int) { if (pos != -1) { pos++; get(); } return *this; } bool operator!=(const TElem &e) const { return pos != e.clen; } };
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485