MSXML von C ++ - ziemlich Druck / indent neu erstellte Dokumente
-
03-07-2019 - |
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
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)