#ifndef ARABICA_SAX_MSXML2_H #define ARABICA_SAX_MSXML2_H //--------------------------------------------------------------------------- // A SAX2 wrapper class for MSXML component. //--------------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include #include // Include the MSXML definitions. #include // // Declare the 'smart pointer' type to simplify COM handling. #include _COM_SMARTPTR_TYPEDEF(ISAXXMLReader, __uuidof(ISAXXMLReader)); namespace Arabica { namespace SAX { struct COMInitializer_tag { }; /** * use this as COMInitializer_type if you call * CoInitialize/CoInitializeEx in your own code */ class COMExternalInitializer : public COMInitializer_tag { public: COMExternalInitializer() { } ~COMExternalInitializer() { } }; // COMExternalInitializer class COMSingleThreadInitializer : public COMInitializer_tag { public: COMSingleThreadInitializer() { ::CoInitialize(NULL); } ~COMSingleThreadInitializer() { ::CoUninitialize(); } }; // COMSingleThreadInitializer #if(_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM) class COMMultiThreadInitializer : public COMInitializer_tag { public: COMMultiThreadInitializer() { ::CoInitializeEx(NULL, COINIT_MULTITHREADED); } ~COMMultiThreadInitializer() { ::CoUninitialize(); } }; #endif template class msxml2_wrapper : public SAX::XMLReaderInterface::type> { public: typedef SAX::XMLReaderInterface, T0, T1>::type> XMLReaderT; typedef typename XMLReaderT::string_adaptor string_adaptor; typedef typename Arabica::get_param::type COMInitializer_type; typedef SAX::EntityResolver entityResolverT; typedef SAX::DTDHandler dtdHandlerT; typedef SAX::ContentHandler contentHandlerT; typedef SAX::DeclHandler declHandlerT; typedef SAX::LexicalHandler lexicalHandlerT; typedef SAX::InputSource inputSourceT; typedef SAX::Locator locatorT; typedef SAX::ErrorHandler errorHandlerT; typedef SAX::Attributes attributesT; msxml2_wrapper(); virtual ~msxml2_wrapper(); ///////////////////////////////////////////////// // Configuration virtual bool getFeature(const string_type& name) const; virtual void setFeature(const string_type& name, bool value); ///////////////////////////////////////////////// // Event Handlers /* MSXML does not use EntityResolver currently */ virtual void setEntityResolver(entityResolverT& resolver) { } virtual entityResolverT* getEntityResolver() const { return 0; } virtual void setDTDHandler(dtdHandlerT& handler) { dtdHandler_.setDTDHandler(handler); } virtual dtdHandlerT* getDTDHandler() const { return dtdHandler_.getDTDHandler(); } virtual void setContentHandler(contentHandlerT& handler) { contentHandler_.setContentHandler(handler); } virtual contentHandlerT* getContentHandler() const { return contentHandler_.getContentHandler(); } virtual void setErrorHandler(errorHandlerT& handler); virtual errorHandlerT* getErrorHandler() const { return errorHandler_.getErrorHandler(); } virtual void setDeclHandler(declHandlerT& handler) { declHandler_.setDeclHandler(handler); } virtual declHandlerT* getDeclHandler() const { return declHandler_.getDeclHandler(); } virtual void setLexicalHandler(lexicalHandlerT& handler) { lexicalHandler_.setLexicalHandler(handler); } virtual lexicalHandlerT* getLexicalHandler() const { return lexicalHandler_.getLexicalHandler(); } ////////////////////////////////////////////////// // Parsing virtual void parse(inputSourceT& input); protected: virtual std::auto_ptr doGetProperty(const string_type& name) { if(name == properties_.lexicalHandler) { Property* prop = new Property(lexicalHandler_.getLexicalHandler()); return std::auto_ptr(prop); } if(name == properties_.declHandler) { Property* prop = new Property(declHandler_.getDeclHandler()); return std::auto_ptr(prop); } throw SAX::SAXNotRecognizedException("Property not recognized "); } // doGetProperty virtual void doSetProperty(const string_type& name, std::auto_ptr value) { if(name == properties_.lexicalHandler) { Property* prop = dynamic_cast*>(value.get()); if(!prop) throw std::runtime_error("bad_cast: Property LexicalHandler is wrong type, should be SAX::LexicalHandler&"); lexicalHandler_.setLexicalHandler(prop->get()); return; } // if ... if(name == properties_.declHandler) { Property* prop = dynamic_cast*>(value.get()); if(!prop) throw std::runtime_error("bad_cast: Property DeclHandler is wrong type, should be SAX::DeclHandler&"); declHandler_.setDeclHandler(prop->get()); return; } // if ... throw SAX::SAXNotRecognizedException("Property not recognized "); } // doSetProperty private: ////////////////////////////////////////////////////// // COM interface -> C++ interface adaptors class LocatorAdaptor : public locatorT { public: LocatorAdaptor() : locator_(0) { } LocatorAdaptor(ISAXLocator __RPC_FAR* locator) : locator_(0) { setLocator(locator); } ~LocatorAdaptor() { setLocator(0); } string_type getPublicId() const { if(!locator_) return string_type(); const wchar_t* pwchPublicId; locator_->getPublicId(&pwchPublicId); string_type publicId(string_adaptor::construct_from_utf16(pwchPublicId)); return publicId; } // getPublicId string_type getSystemId() const { if(!locator_) return string_type(); const wchar_t* pwchSystemId; locator_->getSystemId(&pwchSystemId); string_type systemId(string_adaptor::construct_from_utf16(pwchSystemId)); return systemId; } // getSystemId int getLineNumber() const { if(!locator_) return -1; int lineNumber; locator_->getLineNumber(&lineNumber); return lineNumber; } // getLineNumber int getColumnNumber() const { if(!locator_) return -1; int columnNumber; locator_->getColumnNumber(&columnNumber); return columnNumber; } // getColumnNumber void setLocator(ISAXLocator __RPC_FAR* locator) { locator_ = locator; // no need to AddRef or Release as the ISAXLocator points to the MSXML instance // and we'll clean that up properly anyway } // setLocator private: ISAXLocator __RPC_FAR *locator_; }; // class LocatorAdaptor class DTDHandlerAdaptor : public ISAXDTDHandler { public: DTDHandlerAdaptor() : dtdHandler_(0) { } ~DTDHandlerAdaptor() { } void setDTDHandler(dtdHandlerT& handler) { dtdHandler_ = &handler; } dtdHandlerT* getDTDHandler() const { return dtdHandler_; } virtual HRESULT STDMETHODCALLTYPE notationDecl( /* [in] */ const wchar_t *pwchName, /* [in] */ int cchName, /* [in] */ const wchar_t *pwchPublicId, /* [in] */ int cchPublicId, /* [in] */ const wchar_t *pwchSystemId, /* [in] */ int cchSystemId) { if(dtdHandler_) dtdHandler_->notationDecl(string_adaptor::construct_from_utf16(pwchName, cchName), string_adaptor::construct_from_utf16(pwchPublicId, cchPublicId), string_adaptor::construct_from_utf16(pwchSystemId, cchSystemId)); return S_OK; } // notationDecl virtual HRESULT STDMETHODCALLTYPE unparsedEntityDecl( /* [in] */ const wchar_t *pwchName, /* [in] */ int cchName, /* [in] */ const wchar_t *pwchPublicId, /* [in] */ int cchPublicId, /* [in] */ const wchar_t *pwchSystemId, /* [in] */ int cchSystemId, /* [in] */ const wchar_t *pwchNotationName, /* [in] */ int cchNotationName) { if(dtdHandler_) dtdHandler_->unparsedEntityDecl(string_adaptor::construct_from_utf16(pwchName, cchName), string_adaptor::construct_from_utf16(pwchPublicId, cchPublicId), string_adaptor::construct_from_utf16(pwchSystemId, cchSystemId), string_adaptor::construct_from_utf16(pwchNotationName, cchNotationName)); return S_OK; } // unparsedEntityDecl // satify COM interface even if we're not a COM object long __stdcall QueryInterface(const struct _GUID &riid,void **ppvObject) { return 0; } unsigned long __stdcall AddRef() { return 0; } unsigned long __stdcall Release() { return 0; } private: dtdHandlerT* dtdHandler_; }; // class DTDHandlerAdaptor class ErrorHandlerAdaptor : public ISAXErrorHandler { public: ErrorHandlerAdaptor() : errorHandler_(0), bWarning_(false), bError_(false), bFatal_(false), eWarning_("none"), eError_("none"), eFatal_("none") { } virtual ~ErrorHandlerAdaptor() { } void setErrorHandler(errorHandlerT& handler) { errorHandler_ = &handler; } errorHandlerT* getErrorHandler() const { return errorHandler_; } void setSupplementaryMessage(const std::exception& supplementary) { supplementary_ = supplementary.what(); } // setSupplementaryMessage virtual HRESULT STDMETHODCALLTYPE error( /* [in] */ ISAXLocator *pLocator, /* [in] */ const wchar_t *pwchErrorMessage, /* [in] */ HRESULT hrErrorCode) { bError_ = true; eError_ = SAXParseExceptionT(formatError(pwchErrorMessage), LocatorAdaptor(pLocator)); return S_OK; } // error virtual HRESULT STDMETHODCALLTYPE fatalError( /* [in] */ ISAXLocator *pLocator, /* [in] */ const wchar_t *pwchErrorMessage, /* [in] */ HRESULT hrErrorCode) { bFatal_ = true; eFatal_ = SAXParseExceptionT(formatError(pwchErrorMessage), LocatorAdaptor(pLocator)); return S_FALSE; } // fatalError virtual HRESULT STDMETHODCALLTYPE ignorableWarning( /* [in] */ ISAXLocator *pLocator, /* [in] */ const wchar_t *pwchErrorMessage, /* [in] */ HRESULT hrErrorCode) { bWarning_ = true; eWarning_ = SAXParseExceptionT(formatError(pwchErrorMessage), LocatorAdaptor(pLocator)); return S_OK; } // ignorableWarning void report() { if(!errorHandler_) return; bool bWarning = bWarning_; bool bError = bError_; bool bFatal = bFatal_; bWarning_ = bError_ = bFatal_ = false; if(bFatal) errorHandler_->fatalError(eFatal_); if(bError) errorHandler_->error(eError_); if(bWarning) errorHandler_->warning(eWarning_); } // report // satisfy COM interface even if we're not a COM object long __stdcall QueryInterface(const struct _GUID &riid,void **ppvObject) { return 0; } unsigned long __stdcall AddRef() { return 0; } unsigned long __stdcall Release() { return 0; } private: std::string formatError(const wchar_t *pwchErrorMessage) const { std::string errorMsg = string_adaptor::asStdString((string_adaptor::construct_from_utf16(pwchErrorMessage))); if(!supplementary_.empty()) errorMsg += ": " + supplementary_; return errorMsg; } // formatError ErrorHandlerAdaptor(const ErrorHandlerAdaptor&); typedef SAX::SAXParseException SAXParseExceptionT; bool bWarning_; bool bError_; bool bFatal_; SAXParseExceptionT eWarning_; SAXParseExceptionT eError_; SAXParseExceptionT eFatal_; std::string supplementary_; errorHandlerT* errorHandler_; }; // class ErrorHandlerAdaptor class ContentHandlerAdaptor : public ISAXContentHandler { public: ContentHandlerAdaptor(ErrorHandlerAdaptor& eh) : contentHandler_(0), eh_(eh) { } ~ContentHandlerAdaptor() { } void setContentHandler(contentHandlerT& handler) { contentHandler_ = &handler; } contentHandlerT* getContentHandler() const { return contentHandler_; } virtual HRESULT STDMETHODCALLTYPE putDocumentLocator( /* [in] */ ISAXLocator *pLocator) { locator_.setLocator(pLocator); if(contentHandler_) try { contentHandler_->setDocumentLocator(locator_); } catch(const std::exception& e) { eh_.setSupplementaryMessage(e); throw; } // catch catch(...) { throw; } return S_OK; } // putDocumentLocation virtual HRESULT STDMETHODCALLTYPE startDocument( void) { if(contentHandler_) try { contentHandler_->startDocument(); } catch(const std::exception& e) { eh_.setSupplementaryMessage(e); throw; } // catch catch(...) { throw; } return S_OK; } // startDocument virtual HRESULT STDMETHODCALLTYPE endDocument( void) { if(contentHandler_) try { contentHandler_->endDocument(); } catch(const std::exception& e) { eh_.setSupplementaryMessage(e); throw; } // catch catch(...) { throw; } return S_OK; } // endDocument virtual HRESULT STDMETHODCALLTYPE startPrefixMapping( /* [in] */ const wchar_t *pwchPrefix, /* [in] */ int cchPrefix, /* [in] */ const wchar_t *pwchUri, /* [in] */ int cchUri) { if(contentHandler_) try { contentHandler_->startPrefixMapping(string_adaptor::construct_from_utf16(pwchPrefix, cchPrefix), string_adaptor::construct_from_utf16(pwchUri, cchUri)); } catch(const std::exception& e) { eh_.setSupplementaryMessage(e); throw; } // catch catch(...) { throw; } return S_OK; } // startPrefixMapping virtual HRESULT STDMETHODCALLTYPE endPrefixMapping( /* [in] */ const wchar_t *pwchPrefix, /* [in] */ int cchPrefix) { if(contentHandler_) try { contentHandler_->endPrefixMapping(string_adaptor::construct_from_utf16(pwchPrefix, cchPrefix)); } catch(const std::exception& e) { eh_.setSupplementaryMessage(e); throw; } // catch catch(...) { throw; } return S_OK; } // endPrefixMapping virtual HRESULT STDMETHODCALLTYPE startElement( /* [in] */ const wchar_t *pwchNamespaceUri, /* [in] */ int cchNamespaceUri, /* [in] */ const wchar_t *pwchLocalName, /* [in] */ int cchLocalName, /* [in] */ const wchar_t *pwchQName, /* [in] */ int cchQName, /* [in] */ ISAXAttributes *pAttributes) { if(contentHandler_) { try { AttributesAdaptor attrs(pAttributes); contentHandler_->startElement(string_adaptor::construct_from_utf16(pwchNamespaceUri, cchNamespaceUri), string_adaptor::construct_from_utf16(pwchLocalName, cchLocalName), string_adaptor::construct_from_utf16(pwchQName, cchQName), attrs); } catch(const std::exception& e) { eh_.setSupplementaryMessage(e); throw; } // catch catch(...) { throw; } } // if ... return S_OK; } // startElement virtual HRESULT STDMETHODCALLTYPE endElement( /* [in] */ const wchar_t *pwchNamespaceUri, /* [in] */ int cchNamespaceUri, /* [in] */ const wchar_t *pwchLocalName, /* [in] */ int cchLocalName, /* [in] */ const wchar_t *pwchQName, /* [in] */ int cchQName) { if(contentHandler_) try { contentHandler_->endElement(string_adaptor::construct_from_utf16(pwchNamespaceUri, cchNamespaceUri), string_adaptor::construct_from_utf16(pwchLocalName, cchLocalName), string_adaptor::construct_from_utf16(pwchQName, cchQName)); } catch(const std::exception& e) { eh_.setSupplementaryMessage(e); throw; } // catch catch(...) { throw; } return S_OK; } // endElement virtual HRESULT STDMETHODCALLTYPE characters( /* [in] */ const wchar_t *pwchChars, /* [in] */ int cchChars) { if(contentHandler_) try { contentHandler_->characters(string_adaptor::construct_from_utf16(pwchChars, cchChars)); } catch(const std::exception& e) { eh_.setSupplementaryMessage(e); throw; } // catch catch(...) { throw; } return S_OK; } // characters virtual HRESULT STDMETHODCALLTYPE ignorableWhitespace( /* [in] */ const wchar_t *pwchChars, /* [in] */ int cchChars) { if(contentHandler_) try { contentHandler_->ignorableWhitespace(string_adaptor::construct_from_utf16(pwchChars, cchChars)); } catch(const std::exception& e) { eh_.setSupplementaryMessage(e); throw; } // catch catch(...) { throw; } return S_OK; } // ignorableWhitespace virtual HRESULT STDMETHODCALLTYPE processingInstruction( /* [in] */ const wchar_t *pwchTarget, /* [in] */ int cchTarget, /* [in] */ const wchar_t *pwchData, /* [in] */ int cchData) { if(contentHandler_) try { contentHandler_->processingInstruction(string_adaptor::construct_from_utf16(pwchTarget, cchTarget), string_adaptor::construct_from_utf16(pwchData, cchData)); } catch(const std::exception& e) { eh_.setSupplementaryMessage(e); throw; } // catch catch(...) { throw; } return S_OK; } // processingInstruction virtual HRESULT STDMETHODCALLTYPE skippedEntity( /* [in] */ const wchar_t *pwchName, /* [in] */ int cchName) { if(contentHandler_) try { contentHandler_->skippedEntity(string_adaptor::construct_from_utf16(pwchName, cchName)); } catch(const std::exception& e) { eh_.setSupplementaryMessage(e); throw; } // catch catch(...) { throw; } return S_OK; } // skippedEntity // satisfy COM interface even if we're not a COM object long __stdcall QueryInterface(const struct _GUID &riid,void **ppvObject) { return 0; } unsigned long __stdcall AddRef() { return 0; } unsigned long __stdcall Release() { return 0; } private: //////////////////////////////////////////////// // member varaibles contentHandlerT* contentHandler_; ErrorHandlerAdaptor& eh_; LocatorAdaptor locator_; ////////////////////////////////////////////////////// // COM interface -> C++ interface adaptors class AttributesAdaptor : public attributesT { public: AttributesAdaptor(ISAXAttributes __RPC_FAR *pAttributes) : attributes_(pAttributes) { } ~AttributesAdaptor() { } ///////////////////////// // indexed access virtual int getLength() const { int length; attributes_->getLength(&length); return length; } // getLength virtual string_type getURI(unsigned int index) const { const wchar_t* pwchUri; int cchUri; HRESULT hr = attributes_->getURI(index, &pwchUri, &cchUri); if (FAILED(hr)) return string_type(); string_type uri(string_adaptor::construct_from_utf16(pwchUri, cchUri)); return uri; } // getURI virtual string_type getLocalName(unsigned int index) const { const wchar_t* pwchLocalName; int cchLocalName; HRESULT hr = attributes_->getLocalName(index, &pwchLocalName, &cchLocalName); if (FAILED(hr)) return string_type(); string_type localName(string_adaptor::construct_from_utf16(pwchLocalName, cchLocalName)); return localName; } // getLocalName virtual string_type getQName(unsigned int index) const { const wchar_t* pwchQName; int cchQName; HRESULT hr = attributes_->getQName(index, &pwchQName, &cchQName); if (FAILED(hr)) return string_type(); string_type qName(string_adaptor::construct_from_utf16(pwchQName, cchQName)); return qName; } // getQName virtual string_type getType(unsigned int index) const { const wchar_t* pwchType; int cchType; HRESULT hr = attributes_->getType(index, &pwchType, &cchType); if (FAILED(hr)) return string_type(); string_type type(string_adaptor::construct_from_utf16(pwchType, cchType)); return type; } // getType virtual string_type getValue(unsigned int index) const { const wchar_t* pwchValue; int cchValue; HRESULT hr = attributes_->getValue(index, &pwchValue, &cchValue); if (FAILED(hr)) return string_type(); string_type value(string_adaptor::construct_from_utf16(pwchValue, cchValue)); return value; } // getValue ///////////////////////// // name based query virtual int getIndex(const string_type& uri, const string_type& localName) const { int index = -1; std::wstring wUri(string_adaptor::asStdWString(uri)); std::wstring wLocalName(string_adaptor::asStdWString(localName)); HRESULT hr = attributes_->getIndexFromName(wUri.data(), static_cast(wUri.length()), wLocalName.data(), static_cast(wLocalName.length()), &index); return index; } // getIndex virtual int getIndex(const string_type& qName) const { int index = -1; std::wstring wQName(string_adaptor::asStdWString(qName)); attributes_->getIndexFromQName(wQName.data(), static_cast(wQName.length()), &index); return index; } // getIndex virtual string_type getType(const string_type& uri, const string_type& localName) const { const wchar_t* pwchType; int cchType; std::wstring wUri(string_adaptor::asStdWString(uri)); std::wstring wLocalName(string_adaptor::asStdWString(localName)); HRESULT hr = attributes_->getTypeFromName(wUri.data(), static_cast(wUri.length()), wLocalName.data(), static_cast(wLocalName.length()), &pwchType, &cchType); if (FAILED(hr)) return string_type(); string_type type(string_adaptor::construct_from_utf16(pwchType, cchType)); return type; } // getType virtual string_type getType(const string_type& qName) const { const wchar_t* pwchType; int cchType; std::wstring wQName(string_adaptor::asStdWString(qName)); HRESULT hr = attributes_->getTypeFromQName(wQName.data(), static_cast(wQName.length()), &pwchType, &cchType); if (FAILED(hr)) return string_type(); string_type type(string_adaptor::construct_from_utf16(pwchType, cchType)); return type; } // getType virtual string_type getValue(const string_type& uri, const string_type& localName) const { const wchar_t* pwchValue; int cchValue; std::wstring wUri(string_adaptor::asStdWString(uri)); std::wstring wLocalName(string_adaptor::asStdWString(localName)); HRESULT hr = attributes_->getValueFromName(wUri.data(), static_cast(wUri.length()), wLocalName.data(), static_cast(wLocalName.length()), &pwchValue, &cchValue); if (FAILED(hr)) return string_type(); string_type value(string_adaptor::construct_from_utf16(pwchValue, cchValue)); return value; } // getValue virtual string_type getValue(const string_type& qname) const { const wchar_t* pwchValue; int cchValue; std::wstring wQName(string_adaptor::asStdWString(qname)); HRESULT hr = attributes_->getValueFromQName(wQName.data(), static_cast(wQName.length()), &pwchValue, &cchValue); if (FAILED(hr)) return string_type(); string_type value(string_adaptor::construct_from_utf16(pwchValue, cchValue)); return value; } // getValue private: ISAXAttributes __RPC_FAR *attributes_; AttributesAdaptor(); }; // class AttributesAdaptor }; // class ContentHandlerAdaptor class LexicalHandlerAdaptor : public ISAXLexicalHandler { public: LexicalHandlerAdaptor() : lexicalHandler_(0) { } virtual ~LexicalHandlerAdaptor() { } void setLexicalHandler(lexicalHandlerT& handler) { lexicalHandler_ = &handler; } lexicalHandlerT* getLexicalHandler() const { return lexicalHandler_; } virtual HRESULT STDMETHODCALLTYPE startDTD( /* [in] */ const wchar_t *pwchName, /* [in] */ int cchName, /* [in] */ const wchar_t *pwchPublicId, /* [in] */ int cchPublicId, /* [in] */ const wchar_t *pwchSystemId, /* [in] */ int cchSystemId) { if(lexicalHandler_) lexicalHandler_->startDTD(string_adaptor::construct_from_utf16(pwchName, cchName), string_adaptor::construct_from_utf16(pwchPublicId, cchPublicId), string_adaptor::construct_from_utf16(pwchSystemId, cchSystemId)); return S_OK; } // startDTD virtual HRESULT STDMETHODCALLTYPE endDTD( void) { if(lexicalHandler_) lexicalHandler_->endDTD(); return S_OK; } // endDTD virtual HRESULT STDMETHODCALLTYPE startEntity( /* [in] */ const wchar_t *pwchName, /* [in] */ int cchName) { if(lexicalHandler_) lexicalHandler_->startEntity(string_adaptor::construct_from_utf16(pwchName, cchName)); return S_OK; } // startEntity virtual HRESULT STDMETHODCALLTYPE endEntity( /* [in] */ const wchar_t *pwchName, /* [in] */ int cchName) { if(lexicalHandler_) lexicalHandler_->endEntity(string_adaptor::construct_from_utf16(pwchName, cchName)); return S_OK; } // endEntity virtual HRESULT __stdcall startCDATA() { if(lexicalHandler_) lexicalHandler_->startCDATA(); return S_OK; } // startCDATA virtual HRESULT __stdcall endCDATA() { if(lexicalHandler_) lexicalHandler_->endCDATA(); return S_OK; } // endCDATA virtual HRESULT STDMETHODCALLTYPE comment( /* [in] */ const wchar_t *pwchChars, /* [in] */ int cchChars) { if(lexicalHandler_) lexicalHandler_->comment(string_adaptor::construct_from_utf16(pwchChars, cchChars)); return S_OK; } // comment // satisfy COM interface even if we're not a COM object long __stdcall QueryInterface(const struct _GUID &riid,void **ppvObject) { // we have to implement this, because we pass this as an IUnknown but it needs an // ISAXLexicalHandler interface if(riid == __uuidof(ISAXLexicalHandler)) *ppvObject = this; return 0; } // QueryInterface unsigned long __stdcall AddRef() { return 0; } unsigned long __stdcall Release() { return 0; } private: lexicalHandlerT* lexicalHandler_; }; // class LexicalHandlerAdaptor class DeclHandlerAdaptor : public ISAXDeclHandler { public: DeclHandlerAdaptor() : declHandler_(0) { } virtual ~DeclHandlerAdaptor() { } void setDeclHandler(declHandlerT& handler) { declHandler_ = &handler; } declHandlerT* getDeclHandler() const { return declHandler_; } virtual HRESULT STDMETHODCALLTYPE elementDecl( /* [in] */ const wchar_t *pwchName, /* [in] */ int cchName, /* [in] */ const wchar_t *pwchModel, /* [in] */ int cchModel) { if(declHandler_) declHandler_->elementDecl(string_adaptor::construct_from_utf16(pwchName, cchName), string_adaptor::construct_from_utf16(pwchModel, cchModel)); return S_OK; } // elementDecl virtual HRESULT STDMETHODCALLTYPE attributeDecl( /* [in] */ const wchar_t *pwchElementName, /* [in] */ int cchElementName, /* [in] */ const wchar_t *pwchAttributeName, /* [in] */ int cchAttributeName, /* [in] */ const wchar_t *pwchType, /* [in] */ int cchType, /* [in] */ const wchar_t *pwchValueDefault, /* [in] */ int cchValueDefault, /* [in] */ const wchar_t *pwchValue, /* [in] */ int cchValue) { if(declHandler_) declHandler_->attributeDecl(string_adaptor::construct_from_utf16(pwchElementName, cchElementName), string_adaptor::construct_from_utf16(pwchAttributeName, cchAttributeName), string_adaptor::construct_from_utf16(pwchType, cchType), string_adaptor::construct_from_utf16(pwchValueDefault, cchValueDefault), string_adaptor::construct_from_utf16(pwchValue, cchValue)); return S_OK; } // attributeDecl virtual HRESULT STDMETHODCALLTYPE internalEntityDecl( /* [in] */ const wchar_t *pwchName, /* [in] */ int cchName, /* [in] */ const wchar_t *pwchValue, /* [in] */ int cchValue) { if(declHandler_) declHandler_->internalEntityDecl(string_adaptor::construct_from_utf16(pwchName, cchName), string_adaptor::construct_from_utf16(pwchValue, cchValue)); return S_OK; } // internalEntityDecl virtual HRESULT STDMETHODCALLTYPE externalEntityDecl( /* [in] */ const wchar_t *pwchName, /* [in] */ int cchName, /* [in] */ const wchar_t *pwchPublicId, /* [in] */ int cchPublicId, /* [in] */ const wchar_t *pwchSystemId, /* [in] */ int cchSystemId) { if(declHandler_) declHandler_->externalEntityDecl(string_adaptor::construct_from_utf16(pwchName, cchName), string_adaptor::construct_from_utf16(pwchPublicId, cchPublicId), string_adaptor::construct_from_utf16(pwchSystemId, cchSystemId)); return S_OK; } // externalEntityDecl // satisfy COM interface even if we're not a COM object long __stdcall QueryInterface(const struct _GUID &riid,void **ppvObject) { // we have to implement this, because we pass this as an IUnknown but it needs an // ISAXDeclHandler interface if(riid == __uuidof(ISAXDeclHandler)) *ppvObject = reinterpret_cast(this); return 0; } // QueryInterface unsigned long __stdcall AddRef() { return 0; } unsigned long __stdcall Release() { return 0; } private: declHandlerT* declHandler_; }; // class DeclHandlerAdaptor class StreamAdaptor : public ISequentialStream { public: StreamAdaptor(inputSourceT& source) : source_(source) { } // StreamAdaptor virtual HRESULT __stdcall Read(void* pv, ULONG cb, ULONG* pcbRead) { source_.getByteStream()->read(reinterpret_cast(pv), cb); *pcbRead = static_cast(source_.getByteStream()->gcount()); return S_OK; } // Read virtual HRESULT __stdcall Write(const void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbWritten) { return S_FALSE; } // Write // satisfy COM interface even if we're not a COM object long __stdcall QueryInterface(const struct _GUID &riid,void **ppvObject) { // we have to implement this, because we pass this as an IUnknown but it needs an // IStream interface if(riid == __uuidof(ISequentialStream)) { *ppvObject = reinterpret_cast(this); return S_OK; } // if ... return E_NOINTERFACE; } // QueryInterface unsigned long __stdcall AddRef() { return 1; } unsigned long __stdcall Release() { return 1; } private: inputSourceT& source_; }; // StreamAdaptor ////////////////////////////////////////////////////// // member variables COMInitializer_type init; DTDHandlerAdaptor dtdHandler_; ErrorHandlerAdaptor errorHandler_; ContentHandlerAdaptor contentHandler_; LexicalHandlerAdaptor lexicalHandler_; DeclHandlerAdaptor declHandler_; ISAXXMLReaderPtr reader_; SAX::PropertyNames properties_; }; // class msxml template msxml2_wrapper::msxml2_wrapper() : init(), dtdHandler_(), errorHandler_(), contentHandler_(errorHandler_), lexicalHandler_(), declHandler_(), reader_(), properties_() { reader_.CreateInstance("Msxml2.SAXXMLReader.6.0"); if(reader_.GetInterfacePtr() == 0) reader_.CreateInstance("Msxml2.SAXXMLReader.5.0"); if(reader_.GetInterfacePtr() == 0) reader_.CreateInstance("Msxml2.SAXXMLReader.4.0"); if(reader_.GetInterfacePtr() == 0) reader_.CreateInstance("Msxml2.SAXXMLReader.3.0"); if(reader_.GetInterfacePtr() == 0) reader_.CreateInstance(__uuidof(ISAXXMLReader)); if(reader_.GetInterfacePtr() == 0) throw SAXException("MSXML SAX Reader (pre-4.0) could not be instantiated"); reader_->putContentHandler(&contentHandler_); reader_->putErrorHandler(&errorHandler_); reader_->putDTDHandler(&dtdHandler_); VARIANT wrapper; wrapper.vt = VT_UNKNOWN; wrapper.punkVal = static_cast(&lexicalHandler_); reader_->putProperty(L"http://xml.org/sax/properties/lexical-handler", wrapper); wrapper.punkVal = static_cast(&declHandler_); reader_->putProperty(L"http://xml.org/sax/properties/declaration-handler", wrapper); } // msxml2_wrapper template msxml2_wrapper::~msxml2_wrapper() { if(reader_.GetInterfacePtr()) reader_.Release(); } // ~msxml2_wrapper template bool msxml2_wrapper::getFeature(const string_type& name) const { VARIANT_BOOL feature; std::wstring wName(string_adaptor::asStdWString(name)); reader_->getFeature(wName.c_str(), &feature); return (feature == VARIANT_TRUE) ? true : false; } // msxml2_wrapper::getFeature template void msxml2_wrapper::setFeature(const string_type& name, bool value) { std::wstring wName(string_adaptor::asStdWString(name)); reader_->putFeature(wName.c_str(), value); } // setFeature template void msxml2_wrapper::setErrorHandler(errorHandlerT& handler) { errorHandler_.setErrorHandler(handler); } // setErrorHandler template void msxml2_wrapper::parse(inputSourceT& source) { if(source.getByteStream() == 0) { std::wstring wSysId(string_adaptor::asStdWString(source.getSystemId())); reader_->parseURL(wSysId.c_str()); } else { StreamAdaptor sa(source); VARIANT wrapper; wrapper.vt = VT_UNKNOWN; wrapper.punkVal = static_cast(&sa); reader_->parse(wrapper); } // if ... errorHandler_.report(); } // parse } // namespace SAX } // namespace Arabica #endif // end of file