Click here to Skip to main content
15,867,453 members
Articles / Desktop Programming / ATL
Article

ATL PersistXML implementation

Rate me:
Please Sign up or sign in to vote.
5.00/5 (5 votes)
28 Jul 20032 min read 126.5K   1.3K   38   20
Easiest way to add XML persistence to an existing IDispatch based ATL COM object.

Sample Image - atlpersistxmlapp.gif

Introduction

Think, how many times you wanted to add PersistXML support to your existing ATL COM object? It is true, that it is supposed to be as easy as to add IpersistPropertyBagImpl or IpersistStreamInitImpl ATL Templates. Moreover those classes already share the use of property maps.

BEGIN_PROP_MAP( CMyClass )
    PROP_ENTRY_EX( "Caption", DISPID_CAPTION, <BR>      CLSID_MyClassPropPage2, IID_IMyDual1 )
END_PROP_MAP( )

Lets do this to add XML support!

The Interface

I used IPersistVarXML interface name because Microsoft has already taken IPersistXML for Commerce Server 2002 and it was less convenient than I wanted. (It uses BSTR for the XML input output instead of VARIANT).

I designed my own IPersistVarXML interface (see IDL description below). This interface supports VARIANT as XML input and output. In fact it can even use ISAXContentHandlerfor (MXXMLWriter) the XML output!

[
object,
    uuid(B66873EC-BBFF-11D4-A802-112233445566),
    helpstring("IPersistVarXML Interface"),
    pointer_default(unique)
]
interface IPersistVarXML : IUnknown
{
    [propget, helpstring("property ElementName")] 
       HRESULT ElementName([out, retval] BSTR* bstrElementName);
    HRESULT LoadXML([in] VARIANT varSource, [in, optional, 
            defaultvalue(0L)] IUnknown * pAttributes);
    HRESULT SaveXML([in] VARIANT varSource);
};
template <class T> 
class ATL_NO_VTABLE IPersistVarXMLImpl : 
                            public IPersistVarXML, 
                            public ISAXContentHandlerImpl<T>

This implementation makes heavy use of the Microsoft MS XML SDK (version 3 and higher). Therefore you need to have msxml3.dll or higher installed on your machine. (This DLL always comes with all latest versions of MS Internet Explorer or can be installed separately from www.microsoft.com/xml).

Supported properties

If your class is already derived from one of IPerPropertyBrowsingImpl, IPersistPropertyBagImpl, IPersistStreamInitImpl, and ISpecifyPropertyPagesImpl classes and have BEGIN_PROP_MAP() macro, IPersistVarXMLImpl can reuse this and you do not need to do anything extra!

If you need to save an internal object or handle some XML entries “manually”, you can use BEGIN_XML_CONTENT_MAP () macro. It creates one extra MAP for the XML parser and saver. This map is optional.

BEGIN_XML_CONTENT_MAP(CMyClass)
    XML_CONTENT_LOAD_HANDLER("ENTRY", OnENTRY_HandleFunction)
    XML_CONTENT_ENTRY(&m_objInternal1)
    XML_CONTENT_SAVE_ENTRY(&m_objInternal2)
    XML_CONTENT_CREATE_OBJECT( "ObjectName", 
         CLSID_AnObject, OnXMLContextCreateAnObjec)
END_XML_CONTENT_MAP()

HRESULT OnENTRY_HandleFunction(ISAXAttributes * pAttributes);
HRESULT OnXMLContextUser(IPersistVarXML* pAnOblect);

CComObjectGlobal<CMyInternalObject>    m_objInternal1;
CComObjectGlobal<CMyInternalObject>    m_objInternal2;

How to add XML support

To add PersistXML support to your ATL COM object you need:

  • Add include: IPersistVarXMLImpl.h and IPersistVarXMLImpl.cpp in your project.
    #include IPersistVarXMLImpl.h
  • Derive your class from IPersistVarXMLImpl:
    //////////////////////////////////////////////////////
    // CSystemUser
    class ATL_NO_VTABLE CSystemUser : 
        public CComObjectRootEx<CComSingleThreadModel>,
        public CComCoClass<CSystemUser, &CLSID_SystemUser>,
        public IDispatchImpl<ISYSTEMUSER, &LIBID_ATLPERSISTXMLSAMPLELib &IID_ISystemUser,>,
        public IPersistVarXMLImpl<CSystemUser>
    {
  • Modify COM map. Add ISAXContentHandler and IPersistVarXML interfaces to your object.
    BEGIN_COM_MAP(CSystemUser)
        COM_INTERFACE_ENTRY(ISystemUser)
        COM_INTERFACE_ENTRY(IDispatch)
        COM_INTERFACE_ENTRY(ISAXContentHandler)
        COM_INTERFACE_ENTRY(IPersistVarXML)
    END_COM_MAP()
  • Add public member
    unsigned m_bRequiresSave:1;
  • Add and/Or modify property map. Add only properties that need to be XML persistable!
    BEGIN_PROP_MAP(CSystemUser)
        PROP_ENTRY_EX( "Name",    1,    CLSID_NULL,    IID_ISystemUser )
        PROP_ENTRY_EX( "Address", 2,    CLSID_NULL,    IID_ISystemUser )
    END_PROP_MAP()
  • Add XML Context map for extra functionality (handle dynamic object creation and savings, not standard data types support etc.).
    BEGIN_XML_CONTENT_MAP(T)
        XML_CONTENT_SAVE_ENTRY(&m_objInternal)
        XML_CONTENT_LOAD_HANDLER("ALIAS",OnXMLContextAlias)
    END_XML_CONTENT_MAP()

That’s it!

Uses

Use LoadXML(varSource) and SaveXML(varDest) functions of IPersistVarXML to save and load XML content. VarSource can be all supported ISAXXMLReader::parse() Variant types:

"The application can use this method to instruct the reader to begin 
parsing a document from a variety of sources. Supported VARIANT types are: 
VT_BSTR, SafeArray of bytes (VT_ARRAYVT_UI1), VT_UNK(IStream), 
and VT_UNK(ISequentialStream). One-level referencing is also permitted.
VT_BYREF | VT_VARIANT d
VT_BYREF | VT_VARIANT -> VT_BSTR
VT_BYREF | VT_VARIANT -> IStream
VT_BYREF | VT_VARIANT -> VT_ARRAY|VT_UI1."
(MS XML SDK manual)

varDest can be all supported IMXWriter::output() Variant types:

"Determines the output for MXXMLWriter. By default, the output property 
is a BSTR (string) value. You can also set this property to any 
implementation of the IStream interface, and the resulting document 
will be written into the provided IStream. Setting this property to the 
empty value (VT_EMPTY or " ") will return 
output to the internal string and reset it."
(MS XML SDK manual)

Because this implementation uses CComDispatchDriver::PutProperty() and CComDispatchDriver::GetProperty() base class must be IDispatch derived.

Sample application

I have created two Visual Studio 6.0 projects as an example of how easy it is to add XML support to ATL objects:

  • AtlPersistXmlSample.exe – the main Dialog based application and
  • MyObjects.dllSystemUser and classes implementations.

It can be compiled for both Unicode an ASCII platforms. Load AtlPersistXmlSample.dsw workspace in to Visual Studio, build two projects and run. It demonstrates XML file save/restore configuration for whole application and dynamic XML string generation (including all internal classes and collections) and visualization.

Reference material

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralGetting error compiling Pin
Tommy2k24-Jun-04 10:02
Tommy2k24-Jun-04 10:02 
GeneralNothing on the left panel Pin
xmlai18-Sep-03 16:21
xmlai18-Sep-03 16:21 
GeneralRe: Nothing on the left panel Pin
xmlai18-Sep-03 20:27
xmlai18-Sep-03 20:27 
Generalformatting Pin
Nitron30-Jul-03 15:31
Nitron30-Jul-03 15:31 
GeneralRe: formatting Pin
Nitron30-Jul-03 15:33
Nitron30-Jul-03 15:33 
QuestionCan put the two persist methods (load and save) into the ATL interface? Pin
xmlai23-Jul-03 1:18
xmlai23-Jul-03 1:18 
AnswerRe: Can put the two persist methods (load and save) into the ATL interface? Pin
Katasonov23-Jul-03 12:51
Katasonov23-Jul-03 12:51 
GeneralRe: Can put the two persist methods (load and save) into the ATL interface? Pin
xmlai23-Jul-03 20:18
xmlai23-Jul-03 20:18 
GeneralRe: Can put the two persist methods (load and save) into the ATL interface? Pin
Katasonov28-Jul-03 7:10
Katasonov28-Jul-03 7:10 
GeneralThank you a lot! Pin
xmlai28-Jul-03 15:35
xmlai28-Jul-03 15:35 
GeneralQI fails against ISAXAttributes Pin
Luke_Lee11-Mar-03 1:24
Luke_Lee11-Mar-03 1:24 
GeneralRe: QI fails against ISAXAttributes Pin
Katasonov11-Mar-03 5:23
Katasonov11-Mar-03 5:23 
Generalnothing on the right pane Pin
gok19-Dec-02 9:36
professionalgok19-Dec-02 9:36 
GeneralRe: nothing on the right pane Pin
Katasonov19-Dec-02 13:27
Katasonov19-Dec-02 13:27 
GeneralRe: nothing on the right pane Pin
gok19-Dec-02 14:58
professionalgok19-Dec-02 14:58 
GeneralRe: Win2K+IE6+msxml4.dll (-) Pin
gok19-Dec-02 15:00
professionalgok19-Dec-02 15:00 
GeneralExcellent ! Pin
Braulio Dez4-Nov-02 21:01
Braulio Dez4-Nov-02 21:01 
Hey !

Excellent Job, pretty good, so in this way now you can add new properties to the ActiveX control, and it won't crash when loading older/newer versions of the control ( no tag found on the XML, no problem with offsets and that sh...).

So long
Braulio
GeneralTell me if you have used it in any real projects! ;) Pin
Katasonov25-Nov-02 16:53
Katasonov25-Nov-02 16:53 
GeneralRe: Tell me if you have used it in any real projects! ;) Pin
Braulio Dez27-Nov-02 0:04
Braulio Dez27-Nov-02 0:04 
GeneralSmall suggestion... Pin
Paul A. Howes29-Oct-02 2:15
Paul A. Howes29-Oct-02 2:15 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.