arabica/include/SAX/wrappers/saxmsxml2.hpp
Jez Higgins 6bf75264de Completely removed XMLReader setProperty and getProperty member functions.
For nearly everyone, their use can be replaced by either setLexicalHandler
or setDeclHandler. For the particular case of the Xerces extended properties
I'll loop back round and add specific member methods for those.
2020-04-16 20:23:59 +01:00

1042 lines
40 KiB
C++

#ifndef ARABICA_SAX_MSXML2_H
#define ARABICA_SAX_MSXML2_H
//---------------------------------------------------------------------------
// A SAX2 wrapper class for MSXML component.
//---------------------------------------------------------------------------
#include <SAX/ArabicaConfig.hpp>
#include <SAX/XMLReader.hpp>
#include <SAX/InputSource.hpp>
#include <SAX/SAXParseException.hpp>
#include <SAX/SAXNotRecognizedException.hpp>
#include <SAX/SAXNotSupportedException.hpp>
#include <Arabica/StringAdaptor.hpp>
#include <iostream>
#include <Arabica/getparam.hpp>
// Include the MSXML definitions.
#include <msxml2.h>
//
// Declare the 'smart pointer' type to simplify COM handling.
#include <comdef.h>
_COM_SMARTPTR_TYPEDEF(ISAXXMLReader, __uuidof(ISAXXMLReader));
#if defined(_MSC_VER)
# pragma warning( push )
# pragma warning( disable : 6031 )
#endif
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 string_type,
class T0 = Arabica::nil_t,
class T1 = Arabica::nil_t>
class msxml2_wrapper :
public SAX::XMLReaderInterface<string_type,
typename Arabica::get_string_adaptor<string_type, T0, T1>::type>
{
public:
typedef SAX::XMLReaderInterface<string_type, typename Arabica::get_param<Arabica::string_adaptor_tag,
Arabica::default_string_adaptor<string_type>,
T0,
T1>::type> XMLReaderT;
typedef typename XMLReaderT::string_adaptor string_adaptor;
typedef typename Arabica::get_param<COMInitializer_tag,
COMSingleThreadInitializer,
T1,
T0>::type COMInitializer_type;
typedef SAX::EntityResolver<string_type, string_adaptor> entityResolverT;
typedef SAX::DTDHandler<string_type, string_adaptor> dtdHandlerT;
typedef SAX::ContentHandler<string_type, string_adaptor> contentHandlerT;
typedef SAX::DeclHandler<string_type, string_adaptor> declHandlerT;
typedef SAX::LexicalHandler<string_type, string_adaptor> lexicalHandlerT;
typedef SAX::InputSource<string_type, string_adaptor> inputSourceT;
typedef SAX::Locator<string_type, string_adaptor> locatorT;
typedef SAX::ErrorHandler<string_type, string_adaptor> errorHandlerT;
typedef SAX::Attributes<string_type, string_adaptor> 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);
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
size_t getLineNumber() const
{
if(!locator_)
return -1;
int lineNumber;
locator_->getLineNumber(&lineNumber);
return lineNumber;
} // getLineNumber
size_t 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<string_type, string_adaptor> 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<int>(wUri.length()),
wLocalName.data(), static_cast<int>(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<int>(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<int>(wUri.length()),
wLocalName.data(), static_cast<int>(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<int>(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<int>(wUri.length()),
wLocalName.data(), static_cast<int>(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<int>(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<void*>(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<char*>(pv), cb);
*pcbRead = static_cast<ULONG>(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<void*>(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_;
}; // class msxml
template<class string_type, class T0, class T1>
msxml2_wrapper<string_type, T0, T1>::msxml2_wrapper() :
init(),
dtdHandler_(),
errorHandler_(),
contentHandler_(errorHandler_),
lexicalHandler_(),
declHandler_(),
reader_()
{
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<ISAXLexicalHandler*>(&lexicalHandler_);
reader_->putProperty(L"http://xml.org/sax/properties/lexical-handler", wrapper);
wrapper.punkVal = static_cast<ISAXDeclHandler*>(&declHandler_);
reader_->putProperty(L"http://xml.org/sax/properties/declaration-handler", wrapper);
} // msxml2_wrapper
template<class string_type, class T0, class T1>
msxml2_wrapper<string_type, T0, T1>::~msxml2_wrapper()
{
if(reader_.GetInterfacePtr())
reader_.Release();
} // ~msxml2_wrapper
template<class string_type, class T0, class T1>
bool msxml2_wrapper<string_type, T0, T1>::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<class string_type, class T0, class T1>
void msxml2_wrapper<string_type, T0, T1>::setFeature(const string_type& name, bool value)
{
std::wstring wName(string_adaptor::asStdWString(name));
reader_->putFeature(wName.c_str(), value);
} // setFeature
template<class string_type, class T0, class T1>
void msxml2_wrapper<string_type, T0, T1>::setErrorHandler(errorHandlerT& handler)
{
errorHandler_.setErrorHandler(handler);
} // setErrorHandler
template<class string_type, class T0, class T1>
void msxml2_wrapper<string_type, T0, T1>::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<ISequentialStream*>(&sa);
reader_->parse(wrapper);
} // if ...
errorHandler_.report();
} // parse
} // namespace SAX
} // namespace Arabica
#if defined(_MSC_VER)
# pragma warning( pop )
#endif
#endif
// end of file