Красивый XML
От: akademic Украина  
Дата: 11.03.04 10:06
Оценка: 6 (1)
В общем, сделал класс для получения форматированных 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;
};
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.