Это не совсем вопрос, потому что я уже нашел решение. Это заняло у меня много времени, поэтому я хочу объяснить это здесь.
Msxml основан на COM, поэтому его не так просто использовать в C ++, даже если у вас есть полезные классы для решения вопросов выделения памяти. Но написание нового синтаксического анализатора XML было бы намного сложнее, поэтому я хотел использовать msxml.
Проблема:
Мне удалось найти достаточно примеров в Интернете, чтобы использовать msxml с помощью CComPtr
(умный указатель, чтобы не вызывать Release () для каждого IXMLDOMNode вручную), CComBSTR
(для преобразования строк C ++ в Формат COM для строк) и CComVariant
. Эти 3 полезных класса являются классами ATL и требуют #include <atlbase.h>
.
Проблема: Visual Studio 2008 Express (бесплатная версия) не включает ATL.
Решение:
Используйте comutil.h
и comdef.h
, которые включают несколько простых вспомогательных классов:
_bstr_t
заменяет более или менее CComBSTR
_variant_t
заменяет более или менее CComVariant
_com_ptr_t
заменяет косвенно CComPtr
с помощью _COM_SMARTPTR_TYPEDEF
Маленький пример:
#include <msxml.h>
#include <comdef.h>
#include <comutil.h>
// Define some smart pointers for MSXML
_COM_SMARTPTR_TYPEDEF(IXMLDOMDocument, __uuidof(IXMLDOMDocument)); // IXMLDOMDocumentPtr
_COM_SMARTPTR_TYPEDEF(IXMLDOMElement, __uuidof(IXMLDOMElement)); // IXMLDOMElementPtr
_COM_SMARTPTR_TYPEDEF(IXMLDOMNodeList, __uuidof(IXMLDOMNodeList)); // IXMLDOMNodeListPtr
_COM_SMARTPTR_TYPEDEF(IXMLDOMNamedNodeMap, __uuidof(IXMLDOMNamedNodeMap)); // IXMLDOMNamedNodeMapPtr
_COM_SMARTPTR_TYPEDEF(IXMLDOMNode, __uuidof(IXMLDOMNode)); // IXMLDOMNodePtr
void test_msxml()
{
// This program will use COM
CoInitializeEx(NULL, COINIT_MULTITHREADED);
{
// Create parser
IXMLDOMDocumentPtr pXMLDoc;
HRESULT hr = CoCreateInstance(__uuidof (DOMDocument), NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void**)&pXMLDoc);
pXMLDoc->put_validateOnParse(VARIANT_FALSE);
pXMLDoc->put_resolveExternals(VARIANT_FALSE);
pXMLDoc->put_preserveWhiteSpace(VARIANT_FALSE);
// Open file
VARIANT_BOOL bLoadOk;
std::wstring sfilename = L"testfile.xml";
hr = pXMLDoc->load(_variant_t(sfilename.c_str()), &bLoadOk);
// Search for node <testtag>
IXMLDOMNodePtr pNode;
hr = pXMLDoc->selectSingleNode(_bstr_t(L"testtag"), &pNode);
// Read something
_bstr_t bstrText;
hr = pNode->get_text(bstrText.GetAddress());
std::string sSomething = bstrText;
}
// I'm finished with COM
// (Don't call before all IXMLDOMNodePtr are out of scope)
CoUninitialize();
}