我在c ++中用MSXML编写了一个包装器。加载方法如下所示。 代码的问题是它有时无法加载格式良好的XML。
在将xml作为字符串传递之前,我会对xmlns进行字符串搜索,并将所有出现的xmlns替换为xmlns:dns。 在下面的代码中,我删除了bom字符。然后我尝试使用MSXML loadXML方法加载。如果加载成功,我设置名称空间,如代码所示。
Class XmlDocument{
MSXML2::IXMLDOMDocument2Ptr spXMLDOM;
....
}
// XmlDocument方法
void XmlDocument::Initialize()
{
CoInitialize(NULL);
HRESULT hr = spXMLDOM.CreateInstance(__uuidof(MSXML2::DOMDocument60));
if ( FAILED(hr) )
{
throw "Unable to create MSXML:: DOMDocument object";
}
}
bool XmlDocument::LoadXml(const char* xmltext)
{
if(spXMLDOM != NULL)
{
char BOM[3] = {0xEF,0xBB,0xBF};
//detect unicode BOM character
if(strncmp(xmltext,BOM,sizeof(BOM)) == 0)
{
xmltext += 3;
}
VARIANT_BOOL bSuccess = spXMLDOM->loadXML(A2BSTR(xmltext));
if ( bSuccess == VARIANT_TRUE)
{
spXMLDOM->setProperty("SelectionNamespaces","xmlns:dns=\"http://www.w3.org/2005/Atom\"");
return true;
}
}
return false;
}
我试图调试仍然无法理解为什么有时loadXML()无法加载即使是格式良好的xmls。我在代码中做错了什么。非常感谢任何帮助。
由于 哎呀
答案 0 :(得分:3)
有关此特定问题,请参阅Strings Passed to loadXML must be UTF-16 Encoded BSTRs。
总的来说,xml解析器不是为内存字符串解析而设计的,例如: loadXML无法识别BOM,并且对编码有限制。相反,xml解析器是为具有编码检测的字节数组形式设计的,这对于标准解析器至关重要。要更好地利用MSXML,请考虑从IStream或Win32文件加载。
答案 1 :(得分:2)
我不是A2BSTR的粉丝 - 至少你是在泄漏内存,因为返回的BSTR永远不会被释放。
你可以轻松地
VARIANT_BOOL bSuccess = spXMLDOM->loadXML(CComBSTR(xmltext));
这将正确处理内存。
至于它失败的原因 - 您可以向DOMDocument询问其parseError对象IXMLDOMParseError,然后从中获取原因 - 这可能会更清楚地了解真正的问题。
答案 2 :(得分:0)
我们使用
hr = m_pXMLDoc->load(_variant_t(xml_file.c_str()), &varStatus);
hr = m_pXMLDoc->loadXML(_bstr_t(xml_doc.c_str()), &varStatus);
分别用于加载文件和原始xml。