Even my 2 cents arrive 7 years later I think the question still deserves a simple answer wrapped in just a few lines of code, which is possible by using Visual C++'s #import
directive and the native C++ COM support library (offering smart pointers and encapsulating error handling).
Note that like the accepted answer it doesn't try to fit into the CXml
class the OP is using but rather shows the core idea. Also I assume msxml6
.
Pretty-printing to any stream
void PrettyWriteXmlDocument(MSXML2::IXMLDOMDocument* xmlDoc, IStream* stream)
{
MSXML2::IMXWriterPtr writer(__uuidof(MSXML2::MXXMLWriter60));
writer->encoding = L"utf-8";
writer->indent = _variant_t(true);
writer->standalone = _variant_t(true);
writer->output = stream;
MSXML2::ISAXXMLReaderPtr saxReader(__uuidof(MSXML2::SAXXMLReader60));
saxReader->putContentHandler(MSXML2::ISAXContentHandlerPtr(writer));
saxReader->putProperty(PUSHORT(L"http://xml.org/sax/properties/lexical-handler"), writer.GetInterfacePtr());
saxReader->parse(xmlDoc);
}
File stream
If you need a stream writing to a file you need an implementation of the IStream
interface.
wtlext has got a class, which you can use or from which you can deduce how you can write your own.
Another simple solution that has worked well for me is utilising the Ado Stream class:
void PrettySaveXmlDocument(MSXML2::IXMLDOMDocument* xmlDoc, const wchar_t* filePath)
{
ADODB::_StreamPtr stream(__uuidof(ADODB::Stream));
stream->Type = ADODB::adTypeBinary;
stream->Open(vtMissing, ADODB::adModeUnknown, ADODB::adOpenStreamUnspecified, _bstr_t(), _bstr_t());
PrettyWriteXmlDocument(xmlDoc, IStreamPtr(stream));
stream->SaveToFile(filePath, ADODB::adSaveCreateOverWrite);
}
Glueing it together
A simplistic main
function shows this in action:
#include <stdlib.h>
#include <objbase.h>
#include <comutil.h>
#include <comdef.h>
#include <comdefsp.h>
#import <msxml6.dll>
#import <msado60.tlb> rename("EOF", "EndOfFile") // requires: /I $(CommonProgramFiles)\System\ado
void PrettyWriteXmlDocument(MSXML2::IXMLDOMDocument* xmlDoc, IStream* stream);
void PrettySaveXmlDocument(MSXML2::IXMLDOMDocument* xmlDoc, const wchar_t* filePath);
int wmain()
{
CoInitializeEx(nullptr, COINIT_MULTITHREADED);
try
{
MSXML2::IXMLDOMDocumentPtr xmlDoc(__uuidof(MSXML2::DOMDocument60));
xmlDoc->appendChild(xmlDoc->createElement(L"root"));
PrettySaveXmlDocument(xmlDoc, L"xmldoc.xml");
}
catch (const _com_error&)
{
}
CoUninitialize();
return EXIT_SUCCESS;
}
// assume definitions of PrettyWriteXmlDocument and PrettySaveXmlDocument go here