2017-10-14 21 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 있지만 필요할 때 윈도우 기능이 자동으로 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; 
}