В общем, сделал класс для получения форматированных XML данных.
Может получать и отдавать данные в виде строки, стрима, дом документа.
Для стрима и дом документа можно указать свои объекты.
Хедер:
// XMLDOMIndent.h
#pragma once
#include "stdafx.h"
// define USE_MSXML30 to use msxml3, else used msxml4
//#define USE_MSXML30
#ifndef USE_MSXML30
#import "msxml4.dll"
#define UUIDOF_DOMDOCUMENT (__uuidof(MSXML2::DOMDocument40))
#define UUIDOF_MXXMLWRITER (__uuidof(MSXML2::MXXMLWriter40))
#define UUIDOF_SAXXMLREADER (__uuidof(MSXML2::SAXXMLReader40))
#else
#import "msxml3.dll"
#define UUIDOF_DOMDOCUMENT (__uuidof(MSXML2::DOMDocument30))
#define UUIDOF_MXXMLWRITER (__uuidof(MSXML2::MXXMLWriter30))
#define UUIDOF_SAXXMLREADER (__uuidof(MSXML2::SAXXMLReader30))
#endif //#ifndef USE_MSXML30
class CXMLDOMIndent
{
private:
_variant_t varSource;
_bstr_t encoding;
VARIANT_BOOL standalone;
VARIANT_BOOL indent;
VARIANT_BOOL omitXmlDeclaration;
VARIANT_BOOL byteOrderMark;
VARIANT_BOOL disableOutputEscaping;
enum TYPE_OUT {
toBSTR,
toDOM,
toStream
};
private:
bool InternalAttach(_variant_t &varSource);
_variant_t CXMLDOMIndent::GetInternalOutput(_variant_t &output, TYPE_OUT typeout);
public:
CXMLDOMIndent();
~CXMLDOMIndent();
public:
// Attach to document object
bool Attach(MSXML2::IXMLDOMDocument2Ptr doc);
// Attach to xml string
bool Attach(BSTR xmlstr);
// Attach to node object
bool Attach(MSXML2::IXMLDOMNodePtr node);
// Attach to stream object
bool Attach(IStreamPtr stream);
public:
// Get Always in UTF-16 encoding.
BSTR GetXML();
// Get converted document inside Stream
// instrm - это output, если не задан - создаётся новый в памяти.
IStreamPtr GetStream(IStreamPtr instrm = NULL);
// Get XML document.
// pInDoc - это тоже output, если не задан, тоже создаётся
MSXML2::IXMLDOMDocument2Ptr GetXMLDocument(MSXML2::IXMLDOMDocument2Ptr pInDoc = NULL);
public:
//The encoding property has no effect for BSTR or DOM output.
void SetEncoding(LPCWSTR encoding = NULL);
void SetStandalone(VARIANT_BOOL standalone = VARIANT_TRUE);
void SetIndent(VARIANT_BOOL indent = VARIANT_TRUE);
//The omitXMLDeclaration property has no effect on DOM output
void SetOmitXmlDeclaration(VARIANT_BOOL omitXmlDeclaration = VARIANT_FALSE);
// The byteOrderMark property has no effect for BSTR or DOM output.
void SetByteOrderMark(VARIANT_BOOL byteOrderMark = VARIANT_TRUE);
void SetDisableOutputEscaping(VARIANT_BOOL disableOutputEscaping = VARIANT_FALSE);
};
Ну и реализация:
// XMLDOMIndent.cpp
#include "StdAfx.h"
#include "xmldomindent.h"
CXMLDOMIndent::CXMLDOMIndent()
{
this->varSource.Clear();
this->SetEncoding();
this->SetStandalone();
this->SetOmitXmlDeclaration();
this->SetIndent();
this->SetByteOrderMark();
}
CXMLDOMIndent::~CXMLDOMIndent()
{
}
bool CXMLDOMIndent::Attach(MSXML2::IXMLDOMDocument2Ptr doc)
{
if( doc.GetInterfacePtr() == NULL )
{
SetLastError(E_INVALIDARG);
return false;
}
_variant_t var(doc.GetInterfacePtr());
return InternalAttach(var);
};
bool CXMLDOMIndent::Attach(MSXML2::IXMLDOMNodePtr node)
{
if( node.GetInterfacePtr() == NULL )
{
SetLastError(E_INVALIDARG);
return false;
}
MSXML2::IXMLDOMDocument2Ptr pXMLDoc = NULL;
HRESULT hr = pXMLDoc.CreateInstance(UUIDOF_DOMDOCUMENT);
if( FAILED(hr) )
{
SetLastError(hr);
return false;
}
pXMLDoc->appendChild(node);
return Attach(pXMLDoc);
};
bool CXMLDOMIndent::Attach(BSTR xmlstr)
{
_variant_t var(xmlstr);
return InternalAttach(var);
};
bool CXMLDOMIndent::Attach(IStreamPtr stream)
{
if( stream.GetInterfacePtr() == NULL )
{
SetLastError(E_INVALIDARG);
return false;
}
_variant_t var(stream.GetInterfacePtr());
return InternalAttach(var);
};
bool CXMLDOMIndent::InternalAttach(_variant_t &varSource)
{
this->varSource.Attach(varSource);
return true;
};
////=============================================================
//// Setting parameters
void CXMLDOMIndent::SetEncoding(LPCWSTR encoding)
{
if( encoding == NULL )
encoding = L"";
this->encoding = _bstr_t(encoding);
};
void CXMLDOMIndent::SetStandalone(VARIANT_BOOL standalone)
{
this->standalone = standalone;
};
void CXMLDOMIndent::SetIndent(VARIANT_BOOL indent)
{
this->indent = indent;
};
void CXMLDOMIndent::SetOmitXmlDeclaration(VARIANT_BOOL omitXmlDeclaration )
{
this->omitXmlDeclaration = omitXmlDeclaration;
};
void CXMLDOMIndent::SetByteOrderMark(VARIANT_BOOL byteOrderMark)
{
this->byteOrderMark = byteOrderMark;
};
void CXMLDOMIndent::SetDisableOutputEscaping(VARIANT_BOOL disableOutputEscaping)
{
this->disableOutputEscaping = disableOutputEscaping;
};
////=============================================================
BSTR CXMLDOMIndent::GetXML()
{
return _bstr_t(GetInternalOutput(_variant_t(_bstr_t(L"")), TYPE_OUT::toBSTR));
}
IStreamPtr CXMLDOMIndent::GetStream(IStreamPtr instrm)
{
HRESULT hr;
IStreamPtr strm = NULL;
strm = instrm;
if( strm == NULL )
{
// Create stream for output
hr = CreateStreamOnHGlobal(NULL, TRUE, (LPSTREAM *)&strm);
if( FAILED(hr) )
{
SetLastError(hr);
return NULL;
}
}
_variant_t var(strm.GetInterfacePtr());
IStreamPtr outstrm = GetInternalOutput(var, TYPE_OUT::toStream);
var.Clear();
outstrm = NULL;
// Set Position of stream to beginning
LARGE_INTEGER lint;
lint.QuadPart = 0;
hr = strm->Seek(lint, STREAM_SEEK_SET, NULL);
return strm;
};
MSXML2::IXMLDOMDocument2Ptr CXMLDOMIndent::GetXMLDocument(MSXML2::IXMLDOMDocument2Ptr pInDoc)
{
MSXML2::IXMLDOMDocument2Ptr pXMLDoc = NULL;
pXMLDoc = pInDoc;
if( pXMLDoc == NULL )
{ // Create XML Document
HRESULT hr = pXMLDoc.CreateInstance(UUIDOF_DOMDOCUMENT);
if( FAILED(hr) )
{
SetLastError(hr);
return NULL;
}
pXMLDoc->async = VARIANT_FALSE;
pXMLDoc->resolveExternals = VARIANT_FALSE;
//pXMLDoc->validateOnParse = VARIANT_FALSE;
}
IStreamPtr strmin = pXMLDoc;
_variant_t var(strmin.GetInterfacePtr());
_variant_t varout(GetInternalOutput(var, TYPE_OUT::toDOM));
varout.Clear();
var.Clear();
strmin = NULL;
#ifdef _DEBUG
_bstr_t bstr;
bstr = pXMLDoc->xml;
#endif
return pXMLDoc;
};
_variant_t CXMLDOMIndent::GetInternalOutput(_variant_t &output, TYPE_OUT typeout)
{
MSXML2::IMXWriterPtr pWr = NULL;
HRESULT hr = pWr.CreateInstance(UUIDOF_MXXMLWRITER);
if( FAILED(hr) )
{
SetLastError(hr);
return _variant_t();
}
MSXML2::ISAXXMLReaderPtr sr = NULL;
hr = sr.CreateInstance(UUIDOF_SAXXMLREADER);
if( FAILED(hr) )
{
SetLastError(hr);
return _variant_t();
}
pWr->indent = this->indent;
pWr->standalone = this->standalone;
pWr->omitXMLDeclaration = this->omitXmlDeclaration;
if( this->encoding.length() != 0 )
pWr->encoding = this->encoding;
pWr->byteOrderMark = this->byteOrderMark;
// Set reader to writer
MSXML2::ISAXContentHandlerPtr saxch = pWr;
sr->putContentHandler(saxch);
MSXML2::ISAXErrorHandlerPtr saxerr = pWr;
sr->putErrorHandler(saxerr);
//sr->putProperty(L"http://xml.org/sax/properties/lexical-handler", _variant_t(pWr.GetInterfacePtr()));
//sr->putProperty(L"http://xml.org/sax/properties/declaration-handler", _variant_t(pWr.GetInterfacePtr()));
pWr->output = output;
hr = sr->parse(this->varSource);
if( hr != S_OK )
{
SetLastError(hr);
return _variant_t();
}
_variant_t varout(pWr->output);
return varout;
};