2009-01-21 9 views
6

Gerçekten bir soru değil çünkü zaten bir çözüm buldum. Çok zaman aldı, bu yüzden burada açıklamak istiyorum.Visual Studio 2008 Express ile (hiç ATL sınıfı yok) msxml, deli olmadan nasıl kullanılır?

Msxml, COM'a dayanmaktadır, bu nedenle bellek ayırma sorunları ile başa çıkmak için yararlı sınıflara sahip olsanız bile C++'da kullanımı gerçekten kolay değildir. Ancak yeni bir XML ayrıştırıcısını yazmak çok daha zor olurdu, bu yüzden msxml kullanmak istedim.

sorun:

Ben CComBSTR (el her ıxmldomnode Tahliyesine() aramak zorunda kalmamak için akıllı pointer) CComPtr yardımıyla Msxml kullanmak internette yeterince örnekler bulmak mümkün oldu (C++ dizelerini dizeler için COM biçimine dönüştürmek için) ve CComVariant. Bu 3 yararlı sınıf ATL sınıflarıdır ve bir #include <atlbase.h>'a ihtiyaç duyar.

Sorun: Visual Studio 2008 Express (ücretsiz sürüm) ATL'yi içermiyor.

Çözüm: Bazı basit yardımcı sınıflar dahil

Kullanım comutil.h ve comdef.h:

  • _bstr_t değiştirir az ya da çok CComBSTR
  • _variant_t değiştirir az ya da çok CComVariant
  • _com_ptr_t cümledeki dolaylı olarak

Küçük örnek kullanımı yoluyla: zaten such as eXpat yapılır başka bir XML ayrıştırıcı kullanmak istiyorum

#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(); 
} 
+0

VS2008 express, ATL'yi içermiyor mu? Bu berbat. > :( –

cevap

1

Zaten bir çözümüm olmasına rağmen sorumu gönderdiğim için mutluyum, çünkü birkaç alternatif çözümüm var. Bütün cevapların için teşekkürler.

eXpat gibi başka bir ayrıştırıcıyı veya belki de daha küçük (bu kadar güçlü değil, ancak gereksinimlerim için yeterli) kullanan TinyXML aslında iyi bir fikir olabilir (ve programı başka bir işletim sistemine taşımayı kolaylaştırır). COM kullanımını kolaylaştırmak için bir #import direktifini, görünüşe Microsoft belirli uzantıları kullanarak

da ilginç ve mümkün olduğunca msxml kullanımını kolaylaştırmak için nasıl açıklamak aşağıdaki web sayfasında MSXML in C++ but as elegant as in C#, götürdü.

1

Diğer bir seçenek. ATL'yi ve COM'un karmaşıklıklarını kullanmaktan kaçınır ve kendi uygulamanızı gerçekleştirmekten çok daha kolaydır. Bunu önerdiğim için, msxml'ye bakmanın nedeninin, kendi çözümleyicinizi uygulamak istemediğinizden kaynaklandığına işaret ettim.

+0

Zaten eXpat kullanmayı düşündüm, ama msxml zaten bilgisayardayken, bunu kullanmanın daha küçük bir program oluşturmaya yardımcı olabileceğini düşündüm. Fakat eğer COM zorlukları hakkında önceden bilseydim, eXpat kullanmış olabilirdim .. – Name

7

Belki de #import ifadesini kullanmayı deneyin.

Ben, böyle bir şey yapmak Ben takılmak olduğunuz bir VS6 projesinde kullandım (sadece örnekleme amacıyla kullanılmaktadır; bu benim için çalıştı ama hata kanıtı olduğunu iddia etmeyin):

#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.... 
+0

#import gitmek için kolay ve çok az kod gitmek için harika bir yoldur – galets

+0

"#import" hakkında daha önce hiç duymamıştım (C++ ile şu ana kadar Windows altında olduğundan daha fazla zaman harcadım). Oldukça ilginç görünüyor: – Name

0

Neden Arabica gibi COM formunu koruyacak bazı MSXML sarıcısı kullanmıyorsunuz?

+0

Cevabınız için teşekkürler. Ama XML ayrıştırıcısını kullanmak için gerçekten bir dolaylı katman eklemek istemiyorum. – Name

1

TinyXML'i kullanabilirsiniz. Açık kaynak ve platformdan bağımsız olarak daha fazla.

+0

İlginç, Daha önce bu ayrıştırıcıyı duymamıştım. "eXpat'a alternatif (sayesinde eXpat'ın ne kadar kaynak istediğini kontrol etmedim). – Name