2017-10-14 5 views
1

Si quelque chose de genre là-bas s'il vous plaît passer par la source suivante et dites-moi pourquoi la fonction MSXML "charger" ne parvient pas à charger ce XML.Passer un SAFEARRAY d'octets pour charger la fonction de MSXML

Ici, j'essaie de charger un code XML codé en UTF-8 en utilisant la fonction «load» de l'analyseur MSXML. Et j'ai un BSTR [codé en UTF-16] comme argument, donc j'essaie de le convertir, en SAFEARRAY d'octets pour que je puisse le passer dans la fonction "load" de MSXML. Mais le problème est la fonction de chargement n'a pas réussi à charger ce XML. Si quelqu'un pouvait fournir une solution, je serais vraiment reconnaissant.

#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: Si quelqu'un tente de compiler cette source, vous pouvez obtenir une erreur de lien première fois, ajoutez comsuppw.lib comme une dépendance de liaison dans les paramètres VS. Et XML est codé en UTF-8, donc je ne peux pas utiliser la fonction "LoadXML" dans MSXML.

+1

Il y a beaucoup de problèmes avec votre code. 1) vous * devez * utiliser 'loadXml', il n'y a pas d'autre possibilité. 2) Ce n'est pas parce que vous mettez "utf-8" dans le flux de texte que c'est utf-8. Votre xmlDoc BSTR défini comme ceci est en fait unicode (donc vous pouvez * l'utiliser directement dans loadXml). 3) alors où est votre chaîne UTF-8 d'origine? comment est-il défini techniquement? entrée de tableau d'octets, autre? –

Répondre

1

fichiers XML sont UTF-8, mais il n'y a pas de conversion nécessaire ici parce que les fonctions de Windows vous permet de convertir automatiquement entre UTF-16 et UTF-8 en cas de besoin (sauf entrée/sortie est BYTE* ...)

BSTR besoins nettoyer. Vous pouvez utiliser CComBSTR(str) qui a un nettoyage automatique.

Vous pouvez utiliser const wchar_t* pour transmettre des chaînes à vos propres fonctions. BSTR est requis pour COM, etc.

Comme indiqué dans les commentaires, IXMLDOMDocument::load attend un nom de fichier en entrée. Utilisez IXMLDOMDocument::loadXML dans ce cas.

#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; 
}