即使我的 2 美分在 7 年后到货,我认为这个问题仍然值得一个简单的答案,只需几行代码,这可以通过使用 Visual C++ 的#import
指令和本机 C++ COM 支持库(提供智能指针和封装错误处理)来实现.
请注意,就像接受的答案一样,它不会尝试适应CXml
OP 正在使用的类,而是显示核心思想。我也假设msxml6
.
漂亮地打印到任何流
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);
}
文件流
如果您需要将流写入文件,则需要IStream
接口的实现。
wtlext有一个类,您可以使用它或从中推断如何编写自己的。
另一个对我来说效果很好的简单解决方案是利用 Ado Stream 类:
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);
}
把它粘在一起
一个简单的main
函数显示了这一点:
#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