2017-10-14 20 views
1

何らかの魂がある場合は、以下のソースを参照し、MSXMLの「ロード」関数がこのXMLをロードできない理由を教えてください。バイトのSAFEARRAYを渡してMSXMLの関数をロードする

ここでは、MSXMLパーサの「ロード」機能を使用してUTF-8エンコードされたXMLをロードしようとしています。そして、私は引数としてBSTR [UTF-16エンコード]を持っているので、私はそれをMSXMLの "ロード"機能に渡すことができるように、それをSAFEARRAYバイトに変換しようとしています。しかし、問題は、このXMLをロードできませんでした。誰かが私に解決策を提供できるなら、本当に感謝します。

#include <windows.h> 
#include <objsafe.h> 
#include <objbase.h> 
#include <atlbase.h> 
#include <string> 
#include <comutil.h> 
#include <msxml2.h> 
#include <iostream> 

using namespace std; 

#define STATUS_SUCCESS 0 
#define STATUS_FAIL -1 

long LoadXmlData(BSTR xmlDoc) 
{ 
HRESULT hr = S_OK; 
CComPtr <IXMLDOMDocument> xmlDomDoc = NULL; 
CComPtr <IXMLDOMElement> docRoot = NULL; 
VARIANT_BOOL isParseSucess = FALSE; 

CoInitialize(NULL); 
hr = xmlDomDoc.CoCreateInstance(__uuidof(DOMDocument30)); 
if (FAILED(hr)) 
{ 
    return STATUS_FAIL; 
} 

BYTE HUGEP *pByte; 
int len = WideCharToMultiByte(CP_UTF8, 0, xmlDoc, -1, NULL, 0, NULL, NULL); 
SAFEARRAYBOUND rgsabound[1]; 
rgsabound[0].cElements = len; 
rgsabound[0].lLbound = 0; 

SAFEARRAY* psa = SafeArrayCreate(VT_UI1, 1, rgsabound); 
if (psa != NULL) 
{ 
    hr = SafeArrayAccessData(psa, (void HUGEP**)&pByte); 
    if (!FAILED(hr)) 
    { 
     if (len > 0) 
     { 
      WideCharToMultiByte(CP_UTF8, 0, xmlDoc, -1, (LPSTR)&pByte[0], len, NULL, NULL); 
      //cout << "Converted Byte Array: " << pByte << endl << endl; 
     } 
     else 
     { 
      return STATUS_FAIL; 
     } 
     SafeArrayUnaccessData(psa); 
    } 
} 

VARIANT v; 
VariantInit(&v); 
V_VT(&v) = VT_ARRAY | VT_UI1; 
V_ARRAY(&v) = psa; 

hr = xmlDomDoc->load(v, &isParseSucess); 
//hr = xmlDomDoc->loadXML(xmlDoc, &isParseSucess); //can't use this function because XML is encoded in UTF-8 

if (FAILED(hr) || (!isParseSucess)) 
{ 
    return STATUS_FAIL; 
} 
else 
{ 
    return STATUS_SUCCESS; 
} 
} 

int main() 
{ 
BSTR xmlDoc = SysAllocString(L"<?xml version=\"1.0\" encoding=\"UTF-8\"?> <response> </response> "); 
long ret = LoadXmlData(xmlDoc); 
if (ret == STATUS_SUCCESS) 
{ 
    cout << "MSXML: loading the XML succeeded"; 
} 
else 
{ 
    cout << "MSXML: loading the XML failed"; 
} 
//string str; 
//getline(cin, str); 
return 0; 
} 

PS:誰もがこのソースをコンパイルしようとする場合は、リンクエラー最初にお時間を頂く場合も、VSの設定で、リンカー依存関係としてcomsuppw.libを追加します。 XMLはUTF-8でエンコードされているので、MSXMLで "LoadXML"関数を使用することはできません。

+1

コードには多くの問題があります。 1)あなたは 'loadXml'を使う必要があります。他の可能性はありません。 2)utf-8というテキストストリームに "utf-8"を置くからではありません。このように定義されたxmlDoc BSTRは、実際にはUnicodeです(したがって、loadXmlで直接使用できます)。 3)オリジナルのUTF-8文字列はどこにありますか?それは技術的にどのように定義されていますか?バイト配列の入力、他? –

答えて

1

XMLファイルはUTF-8ですが、必要なときに、Windowsの機能は自動的にUTF-16とUTF-8の間で変換されますので、ここで必要な変換はありません

BSTRニーズ(入力/出力はBYTE* ...でない限り)掃除。自動クリーンアップを持つCComBSTR(str)を使用できます。

const wchar_t*を使用すると、文字列を独自の関数に渡すことができます。 COMなどにはBSTRが必要です。

コメントに記載されているように、IXMLDOMDocument::loadには入力としてファイル名が必要です。この場合はIXMLDOMDocument::loadXMLを使用してください。

#include <iostream> 
#include <windows.h> 
#include <atlbase.h> 
#include <msxml2.h> 

long LoadXmlData(const wchar_t* content) 
{ 
    HRESULT hr = S_FALSE; 
    CComPtr<IXMLDOMDocument> doc = NULL; 
    CComPtr<IXMLDOMElement> docRoot = NULL; 

    hr = doc.CoCreateInstance(__uuidof(DOMDocument30)); 
    if(FAILED(hr)) 
     return S_FALSE; 

    VARIANT_BOOL is_success = FALSE; 
    CComBSTR arg(content); 
    hr = doc->loadXML(arg, &is_success); 

    //if you are loading from a file: 
    //hr = doc->load(CComVariant(L"c:\\test\\test.xml"), &is_success); 

    if(FAILED(hr) || !is_success) 
     return S_FALSE; 

    //if save is needed: 
    //doc->save(CComVariant(L"c:\\test\\test.xml")); 
    return S_OK; 
} 

int main() 
{ 
    CoInitialize(NULL); 

    //ελληνική γλώσσα Greek text for testing 
    CComBSTR data(L"<?xml version=\"1.0\" encoding=\"UTF-8\"?><response>ελληνική γλώσσα</response>"); 
    long ret = LoadXmlData(data); 
    if(ret == S_OK) 
     std::cout << "MSXML: loading the XML succeeded\n"; 
    else 
     std::cout << "MSXML: loading the XML failed\n"; 

    CoUninitialize(); 
    return 0; 
} 
関連する問題