RESOLUTION
The following code loads an XML document from a URL, saves it to a stream, and restores it back into a separate DOMDocument object. If you don't reset the seek pointer, you will receive the error messaged mentioned in the "Symptoms" section of this article.
#import "msxml3.dll"
using namespace MSXML2;
void dump_com_error(_com_error &e)
{
printf("Error\n");
printf("\a\tCode = %08lx\n", e.Error());
printf("\a\tCode meaning = %s", e.ErrorMessage());
_bstr_t bstrSource(e.Source());
_bstr_t bstrDescription(e.Description());
printf("\a\tSource = %s\n", (LPCSTR) bstrSource);
printf("\a\tDescription = %s\n", (LPCSTR) bstrDescription);
}
int main(int argc, char* argv[])
{
CoInitialize(NULL);
try{
IXMLDOMDocumentPtr pXMLDoc;
HRESULT hr = pXMLDoc.CreateInstance(__uuidof(DOMDocument));
pXMLDoc->async = false; // default - true,
hr = pXMLDoc->load("stock.xml");
if(hr!=VARIANT_TRUE)
{
IXMLDOMParseErrorPtr pError;
pError = pXMLDoc->parseError;
_bstr_t parseError =_bstr_t("At line ")+ _bstr_t(pError->Getline()) + _bstr_t("\n")+ _bstr_t(pError->Getreason());
MessageBox(NULL,parseError, "Parse Error",MB_OK);
return 0;
}
CComPtr<IStream> pStream;
hr = CreateStreamOnHGlobal(NULL, true, &pStream);
hr = pXMLDoc->save(pStream.p);
LARGE_INTEGER pos;
pos.QuadPart = 0;
//the key is to reset the seek pointer
pStream->Seek((LARGE_INTEGER)pos, STREAM_SEEK_SET, NULL);
IXMLDOMDocumentPtr pXMLDocNew;
hr = pXMLDocNew.CreateInstance(__uuidof(DOMDocument));
pXMLDocNew->async = false;
hr = pXMLDocNew->load(pStream.p);
if(hr!=VARIANT_TRUE)
{
IXMLDOMParseErrorPtr pError;
pError = pXMLDocNew->parseError;
_bstr_t parseError =_bstr_t("At line ")+ _bstr_t(pError->Getline()) + _bstr_t("\n")+ _bstr_t(pError->Getreason());
MessageBox(NULL,parseError, "Parse Error",MB_OK);
return 0;
}
MessageBox(NULL,(LPTSTR)pXMLDocNew->xml, "XML content",MB_OK);
}
catch(_com_error &e)
{
dump_com_error(e);
}
CoUninitialize();
return 0;
}
If a newer version of MSXML has been installed in side-by-side mode, you must explicitly use the Globally Unique Identifiers (GUIDs) or ProgIDs for that version to run the sample code. For example, MSXML version 4.0 can only be installed in side-by-side mode. For additional information about the code changes that are required to run the sample code with the MSXML 4.0 parser, click the following article number to view the article in the Microsoft Knowledge Base:
305019 INFO: MSXML 4.0 Specific GUIDs and ProgIds
To run the sample code with MSXML 4.0 parser, you need to make following code changes:
- Use #import "msxml4.dll" instead of #import "msxml3.dll".
- Use DOMDocument40 in CreateInstance call, for example
HRESULT hr = pXMLDoc.CreateInstance(__uuidof(DOMDocument40));