我正在尝试确定从资源区域读取XML文件的正确方法,以便将其转换为bstr_t
以传递给XML转换器。
这是我和我的同事到目前为止:
bstr_t LoadXMLFromResource(UINT id)
{
HINSTANCE hInst = AfxGetInstanceHandle();
HRSRC hrSrc = FindResource(hInst, MAKEINTRESOURCE(id), _T("XML"));
CStringW strXML;
if (hrSrc)
{
HGLOBAL hGlobal = LoadResource(hInst, hrSrc);
if (hGlobal)
{
LPVOID xmlBuffer = LockResource(hGlobal);
LPUTF8 leftAngleBracket;
leftAngleBracket = strchr((LPUTF8)xmlBuffer, '<'); // skip over BOM if exists
if (leftAngleBracket)
strXML = leftAngleBracket;
UnlockResource(hGlobal);
}
FreeResource(hGlobal);
}
return bstr_t(strXML);
}
我有点担心使用LPUTF8
。这最初是因为该文件是UTF-8
文件,但是对某些转换问题/冗余存在一些担忧,因此我们正在考虑转移到UTF-16
。但对我来说仍然有点不清楚。此外,我们的XML文件中的第一行是:
<?xml version="1.0" encoding="utf-8"?>
如果我们转到UTF-16
,那当然会改变。
记事本另存为对话框可以保存:UTF-8
,Unicode
或Unicode big endian
。
VS2013 另存为对话框允许保存:Unicode (UTF-8 with signature) - Codepage 65001
,Unicode - Codepage 1200
和Unicode (Big Endian) - Codepage 1201
。第一个条目实际上取决于原件是否有BOM。如果没有BOM,它会说Unicode (UTF-8 without signature) - Codepage ???
我不记得它所说的代码页是什么。它显示了一个或另一个,从不两者。困惑了吗? o.O
因此,如果我们使用不是UTF-8
的 Unicode 编码,我们在XML文件的第一行说明了什么?从我一直在阅读的内容UNICODE is not UTF-16
。
我完全混淆了Windows调用Unicode和UTF-x
标准。
作为参考,这是调用此函数的源:
MSXML2::IXMLDOMDocumentPtr m_pXml;
m_pXml.CreateInstance(__uuidof(MSXML2::DOMDocument60));
m_pXml->async = VARIANT_FALSE;
m_pXml->validateOnParse = VARIANT_FALSE;
m_pXml->resolveExternals = VARIANT_FALSE;
VARIANT_BOOL bRet = m_pXml->loadXML(LoadXMLFromResource(resouceId));
回顾一下,我的问题是,以最少的转换/分配从资源中读取XML文件的“最佳”方式是什么?虽然如果它做了几次可能不是什么大问题,但是我需要一些指标给团队的其他人说明为什么一种方式比另一种更好。如果您有其他指标,请随时加入。
第二个问题是,XML文件中的第一行是什么?
答案 0 :(得分:2)
我认为最好的可能是你让XmlDocument处理编码,并且不要尝试自己做任何有关它们的事情(因此你的代码会自动支持msxml支持的所有编码,你赢得了#t需要关心如何编码源文件)。意思是,您可以将资源作为二进制数据blob 读取,然后将其提供给XmlDocument(作为IStream)。
像这样:
HINSTANCE hInst = AfxGetResourceHandle();
HRSRC hrSrc = FindResource(hInst, MAKEINTRESOURCE(id), _T("XML"));
HGLOBAL hGlobal = LoadResource(hInst, hrSrc);
LPVOID xmlBuffer = LockResource(hGlobal);
ULONG xmlBufferSize = SizeofResource(hInst, hrSrc);
// read the resource into a memory stream as data blob
LPSTREAM pStream = NULL;
CreateStreamOnHGlobal(NULL, TRUE, &pStream);
pStream->Write(xmlBuffer, xmlBufferSize, NULL);
LARGE_INTEGER pos = { 0 }; // rewind
pStream->Seek(pos, 0, NULL);
MSXML2::IXMLDOMDocumentPtr m_pXml;
m_pXml.CreateInstance(__uuidof(MSXML2::DOMDocument60));
m_pXml->async = VARIANT_FALSE;
m_pXml->validateOnParse = VARIANT_FALSE;
m_pXml->resolveExternals = VARIANT_FALSE;
// here we go: load the document from the binary stream
VARIANT_BOOL bRet = m_pXml->load(pStream);