MSXML from C++ - pretty print / indent newly created documents

前端 未结 5 1243
陌清茗
陌清茗 2020-12-31 17:07

I\'m writing out XML files using the MSXML parser, with a wrapper I downloaded from here: http://www.codeproject.com/KB/XML/JW_CXml.aspx. Works great except that when I crea

5条回答
  •  旧巷少年郎
    2020-12-31 17:55

    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 
    #include 
    #include 
    #include 
    #include 
    #import 
    #import  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
    

提交回复
热议问题