mirror of
https://github.com/jezhiggins/arabica
synced 2025-01-14 08:01:49 +01:00
6bf75264de
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.
1042 lines
40 KiB
C++
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
|
|
|