6

私はすでに解決策を見つけているので、それは本当に質問ではありません。かなり時間がかかったので、ここで説明したいと思います。

Msxml は COM に基づいているため、メモリ割り当ての問題を処理するのに役立つクラスがある場合でも、C++ で使用するのは簡単ではありません。しかし、新しい XML パーサーを作成するのははるかに難しいため、msxml を使用したいと考えました。

問題:

( IXMLDOMNodeCComPtrごとに手動で Release() を呼び出さなくても済むようにするためのスマート ポインター)、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_tCComPtrを使用して間接的に置き換えます_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();
}
4

5 に答える 5

7

#importステートメントを使用してみてください。

私はぶらぶらしているVS6プロジェクトでそれを使用しました。あなたはこのようなことをします(説明のみを目的としています。これは私にとってはうまくいきましたが、エラープルーフであるとは主張していません):

#import  "msxml6.dll"

  ...

MSXML2::IXMLDOMDocument2Ptr pdoc;
HRESULT hr = pdoc.CreateInstance(__uuidof(MSXML2::DOMDocument60));
if (!SUCCEEDED(hr)) return hr;

MSXML2::IXMLDOMDocument2Ptr pschema;
HRESULT hr = pschema.CreateInstance(__uuidof(MSXML2::DOMDocument60));
if (!SUCCEEDED(hr)) return hr;

pschema->async=VARIANT_FALSE;
VARIANT_BOOL b;
b = pschema->loadXML(_bstr_t( /* your schema XML here */ ));

MSXML2::IXMLDOMSchemaCollection2Ptr pSchemaCache;
hr = pSchemaCache.CreateInstance(__uuidof(MSXML2::XMLSchemaCache60));
if (!SUCCEEDED(hr)) return hr;

_variant_t vp=pschema.GetInterfacePtr();
pSchemaCache->add(_bstr_t( /* your namespace here */ ),vp); 

pdoc->async=VARIANT_FALSE;
pdoc->schemas = pSchemaCache.GetInterfacePtr();
pdoc->validateOnParse=VARIANT_TRUE;
if (how == e_filename)
    b = pdoc->load(v);
else
    b = pdoc->loadXML(bxmldoc);

pXMLError = pdoc->parseError;
if (pXMLError->errorCode != 0)
    return E_FAIL; // an unhelpful return code, sigh....
于 2009-01-21T22:40:37.280 に答える
1

もう 1 つのオプションは、eXpat など、既に行われている別の XML パーサーを使用することです。ATL や複雑な COM を使用する必要がなく、独自に実装するよりもはるかに簡単です。msxml を見ている理由は、独自のパーサーを実装したくないためであると述べたからです。

于 2009-01-21T22:36:55.730 に答える
1

いくつかの代替ソリューションを取得したため、既に解決策がありましたが、質問を投稿してよかったです。ご回答ありがとうございます。

eXpatなどの別のパーサーまたはおそらく小さい (それほど強力ではありませんが、私のニーズには十分です) TinyXMLを使用することは、実際には良い考えです (また、プログラムを別のオペレーティング システムに簡単に移植できます)。

#importCOM の使用を簡素化するための Microsoft 固有の拡張機能であると思われるディレクティブを使用することも興味深くMSXML in C++ but as elegant as in C#、msxml の使用を可能な限り簡素化する方法を説明している次の Web ページにたどり着きました。

于 2009-01-23T19:28:33.190 に答える
1

TinyXML を使用できます。オープンソースであり、プラットフォームに依存しません。

于 2009-01-22T01:17:05.640 に答える
0

アラビカなど、COM から保護する MSXML ラッパーを使用しないのはなぜですか。

于 2009-01-21T23:00:09.503 に答える