传递字节的SAFEARRAY来加载MSXML的函数
问题描述:
如果有任何一种灵魂在那里请通过以下源代码并告诉我为什么MSXML“加载”函数无法加载此XML。传递字节的SAFEARRAY来加载MSXML的函数
这里我试图使用MSXML解析器的“加载”函数加载UTF-8编码的XML。我有一个BSTR [UTF-16编码]作为参数,所以我试图将它转换成SAFEARRAY字节,以便我可以将它传递到MSXML的“加载”功能。但问题是加载函数无法加载这个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:如果有人试图编译这个源你可以得到一个链接错误第一次加comsuppw.lib在VS设置的连接依赖。而且XML是UTF-8编码的,所以我不能在MSXML中使用“LoadXML”函数。
答
XML文件是UTF-8,但也没有必要,因为当Windows功能将自动UTF-16和UTF-8之间进行转换需要在这里转换(除非输入/输出BYTE*
...)
BSTR
需求清理。您可以使用自动清理的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;
}
您的代码有很多问题。 1)你*必须*使用'loadXml',没有其他可能。 2)这不是因为你在文本流中放置了“utf-8”,而是utf-8。你这样定义的xmlDoc BSTR实际上是unicode(所以你可以直接在loadXml中使用它)。 3)那么你的原始UTF-8字符串在哪里?它在技术上如何定义?字节数组输入,其他? –