Frage

Ich schreibe aus XML-Dateien, um den MSXML-Parser verwenden, mit einem Wrapper ich hier heruntergeladen:

War es hilfreich?

Lösung

Versuchen Sie diese, fand ich vor Jahren im Web.

#include <msxml2.h>

bool FormatDOMDocument (IXMLDOMDocument *pDoc, IStream *pStream)
{

    // Create the writer

    CComPtr <IMXWriter> pMXWriter;
    if (FAILED (pMXWriter.CoCreateInstance(__uuidof (MXXMLWriter), NULL, CLSCTX_ALL)))
    {
        return false;
    }
    CComPtr <ISAXContentHandler> pISAXContentHandler;
    if (FAILED (pMXWriter.QueryInterface(&pISAXContentHandler)))
    {
        return false;
    }
    CComPtr <ISAXErrorHandler> pISAXErrorHandler;
    if (FAILED (pMXWriter.QueryInterface (&pISAXErrorHandler)))
    {
        return false;
    }
    CComPtr <ISAXDTDHandler> pISAXDTDHandler;
    if (FAILED (pMXWriter.QueryInterface (&pISAXDTDHandler)))
    {
        return false;
    }

    if (FAILED (pMXWriter ->put_omitXMLDeclaration (VARIANT_FALSE)) ||
        FAILED (pMXWriter ->put_standalone (VARIANT_TRUE)) ||
        FAILED (pMXWriter ->put_indent (VARIANT_TRUE)) ||
        FAILED (pMXWriter ->put_encoding (L"UTF-8")))
    {
        return false;
    }

    // Create the SAX reader

    CComPtr <ISAXXMLReader> pSAXReader;
    if (FAILED (pSAXReader.CoCreateInstance (__uuidof (SAXXMLReader), NULL, CLSCTX_ALL)))
    {
        return false;
    }

    if (FAILED (pSAXReader ->putContentHandler (pISAXContentHandler)) ||
        FAILED (pSAXReader ->putDTDHandler (pISAXDTDHandler)) ||
        FAILED (pSAXReader ->putErrorHandler (pISAXErrorHandler)) ||
        FAILED (pSAXReader ->putProperty (
        L"http://xml.org/sax/properties/lexical-handler", CComVariant (pMXWriter))) ||
        FAILED (pSAXReader ->putProperty (
        L"http://xml.org/sax/properties/declaration-handler", CComVariant (pMXWriter))))
    {
        return false;
    }

    // Perform the write

    return 
       SUCCEEDED (pMXWriter ->put_output (CComVariant (pStream))) &&
       SUCCEEDED (pSAXReader ->parse (CComVariant (pDoc)));
}

Andere Tipps

Hier ist eine modifizierte Version der akzeptierten Antwort, die im Speicher verwandeln (Änderungen erst in den letzten paar Zeilen, aber ich bin den ganzen Block für die Bequemlichkeit der zukünftigen Leser veröffentlichen):

bool CXml::FormatDOMDocument(IXMLDOMDocument *pDoc)
{
    // Create the writer
    CComPtr <IMXWriter> pMXWriter;
    if (FAILED (pMXWriter.CoCreateInstance(__uuidof (MXXMLWriter), NULL, CLSCTX_ALL))) {
        return false;
    }
    CComPtr <ISAXContentHandler> pISAXContentHandler;
    if (FAILED (pMXWriter.QueryInterface(&pISAXContentHandler))) {
        return false;
    }
    CComPtr <ISAXErrorHandler> pISAXErrorHandler;
    if (FAILED (pMXWriter.QueryInterface (&pISAXErrorHandler))) {
        return false;
    }
    CComPtr <ISAXDTDHandler> pISAXDTDHandler;
    if (FAILED (pMXWriter.QueryInterface (&pISAXDTDHandler))) {
        return false;
    }

    if (FAILED (pMXWriter->put_omitXMLDeclaration (VARIANT_FALSE)) ||
        FAILED (pMXWriter->put_standalone (VARIANT_TRUE)) ||
        FAILED (pMXWriter->put_indent (VARIANT_TRUE)) ||
        FAILED (pMXWriter->put_encoding (L"UTF-8")))
    {
        return false;
    }

    // Create the SAX reader
    CComPtr <ISAXXMLReader> pSAXReader;
    if (FAILED(pSAXReader.CoCreateInstance(__uuidof (SAXXMLReader), NULL, CLSCTX_ALL))) {
        return false;
    }

    if (FAILED(pSAXReader->putContentHandler (pISAXContentHandler)) ||
        FAILED(pSAXReader->putDTDHandler (pISAXDTDHandler)) ||
        FAILED(pSAXReader->putErrorHandler (pISAXErrorHandler)) ||
        FAILED(pSAXReader->putProperty (L"http://xml.org/sax/properties/lexical-handler", CComVariant (pMXWriter))) ||
        FAILED(pSAXReader->putProperty (L"http://xml.org/sax/properties/declaration-handler", CComVariant (pMXWriter))))
    {
        return false;
    }

    // Perform the write
    bool success1 = SUCCEEDED(pMXWriter->put_output(CComVariant(pDoc.GetInterfacePtr())));
    bool success2 = SUCCEEDED(pSAXReader->parse(CComVariant(pDoc.GetInterfacePtr())));

    return success1 && success2;
}

Auch meine 2 Cent ankommen 7 Jahre später denke ich immer noch die Frage eine einfache Antwort in nur wenigen Zeilen Code gewickelt verdient, die mithilfe von Visual C ++ 's #import Richtlinie und die native C ++ COM Support-Bibliothek (bietet intelligente Zeiger möglich ist und Einkapseln Fehlerbehandlung).

Beachten Sie, dass wie die akzeptierte Antwort sie nicht in die CXml Klasse passt versuchen die OP verwendet, sondern zeigt die Kernidee. Auch ich nehme an msxml6.

Pretty-Druck auf jeden Strom

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);
}

Datei-Stream

Wenn Sie einen Stream in eine Datei schreiben Sie eine Implementierung der IStream Schnittstelle benötigen.
wtlext hat eine Klasse bekam, mit dem Sie oder Sie können aus dem ableiten, wie Sie Ihre eigenen schreiben kann.

Eine weitere einfache Lösung, die gut funktioniert hat für mich die Ado Stream-Klasse nutzt:

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);
}

Verleimung es zusammen

Eine verein main Funktion zeigt dies in Aktion:

#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

Es sei denn, die Bibliothek eine Formatoption hat dann die einzige andere Möglichkeit ist XSLT zu verwenden, oder einen externen ziemlich Drucker (ich glaube htmltidy auch xml tun können) Es doen't scheint eine Option in der Codeproject lib zu sein, aber Sie können ein Stylesheet zu MSXML angeben.

Ich habe geschrieben Einrücken einen Sed-Skript vor einiger Zeit für grundlegende xml. Sie können es als externes Eindringkörper verwenden, wenn alles andere fehlschlägt (außer dies xmlindent.sed und Ihre xml verarbeiten mit sed -f xmlindent.sed ). Sie könnten Cygwin oder eine andere Posix-Umgebung benötigen, wenn es zu benutzen.

Hier ist die Quelle:

:a
/>/!N;s/\n/ /;ta
s/  / /g;s/^ *//;s/  */ /g
/^<!--/{
:e
/-->/!N;s/\n//;te
s/-->/\n/;D;
}
/^<[?!][^>]*>/{
H;x;s/\n//;s/>.*$/>/;p;bb
}
/^<\/[^>]*>/{
H;x;s/\n//;s/>.*$/>/;s/^    //;p;bb
}
/^<[^>]*\/>/{
H;x;s/\n//;s/>.*$/>/;p;bb
}
/^<[^>]*[^\/]>/{
H;x;s/\n//;s/>.*$/>/;p;s/^/ /;bb
}
/</!ba
{
H;x;s/\n//;s/ *<.*$//;p;s/[^    ].*$//;x;s/^[^<]*//;ba
}
:b
{
s/[^    ].*$//;x;s/^<[^>]*>//;ba
}

HRMP scheinen Tabs verstümmelt werden ... können Sie kopieren-Abfall von hier statt: XML Einrücken mit sed (1)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top