Listing 2: Major functions of the DocumentContentHandler<Data, Functor> class.

//.....
template <class Data, class Functor>
class DocumentContentHandler : public BaseContentHandler
{ 
protected:
    typedef DocumentContentHandler<Data, Functor>  DocHandlerType;
    typedef map<XmlString, BaseContentHandler*>    ContentHandlerMap;
    typedef ContentHandlerMap::iterator    ContentHandlerIterator;
protected:
    ContentHandlerMap                         m_AllHandlers;
    stack<BaseContentHandler*>                m_ActiveHandlers;
    ISAXXMLReader*                            m_pXMLReader;
public:
    // destructor and other functions not shown
    DocumentContentHandler(const XmlString& strDocumentName,
                            Functor* pFunctor) 
        : BaseContentHandler(strDocumentName) 
    {
        m_AllHandlers.insert(
          ContentHandlerMap::value_type(strDocumentName,this));
          CompositeContentHandler<Data, Functor>*    pHandler = 
                 new DataHandler(Data::GetClassName(),this,pFunctor);
    }
    virtual HRESULT STDMETHODCALLTYPE startElement( 
        /* [in] */ wchar_t __RPC_FAR *pwchNamespaceUri,
        /* [in] */ int cchNamespaceUri,
        /* [in] */ wchar_t __RPC_FAR *pwchLocalName,
        /* [in] */ int cchLocalName,
        /* [in] */ wchar_t __RPC_FAR *pwchRawName,
        /* [in] */ int cchRawName,
        /* [in] */ ISAXAttributes __RPC_FAR *pAttributes)
    {
        ContentHandlerIterator iter = 
            m_AllHandlers.find(XmlString(pwchLocalName));
        if (iter != m_AllHandlers.end())
        {
            m_ActiveHandlers.push(iter->second);
            m_pXMLReader->putContentHandler(iter->second);
        }
        return S_OK;
    }
    virtual HRESULT STDMETHODCALLTYPE endElement( 
        /* [in] */ wchar_t __RPC_FAR *pwchNamespaceUri,
        /* [in] */ int cchNamespaceUri,
        /* [in] */ wchar_t __RPC_FAR *pwchLocalName,
        /* [in] */ int cchLocalName,
        /* [in] */ wchar_t __RPC_FAR *pwchRawName,
        /* [in] */ int cchRawName)
    {
        if(!m_ActiveHandlers.empty())
            m_ActiveHandlers.pop();
        if(!m_ActiveHandlers.empty())
            m_pXMLReader->putContentHandler(
                m_ActiveHandlers.top());
        return S_OK;
    }
};