Поскольку все поддерживаемые версии Windows (включая Windows XP SP3) включают MSXML 6.0, вам следует использовать MS XML 6.0.Вы должны реализовать собственный ISAXContentHandler класс, и обычно я реализую ISequentialStream класс.
Реализация ISequentialStream для анализа:
class MySequentialStream : public ISequentialStream
{
public:
MySequentialStream( istream &is )
: is(is), ref_count(0)
{
InitializeCriticalSection( &this->critical_section );
};
virtual ~MySequentialStream( void )
{
DeleteCriticalSection( &this->critical_section );
}
virtual HRESULT __stdcall QueryInterface( const IID &riid, void ** ppvObject )
{
if ( riid == IID_ISequentialStream )
{
*ppvObject = static_cast<void*>(this);
this->AddRef();
return S_OK;
}
if (riid == IID_IUnknown)
{
*ppvObject = static_cast<void*>(this);
this->AddRef();
return S_OK;
}
*ppvObject = 0;
return E_NOINTERFACE;
};
virtual ULONG __stdcall AddRef( void )
{
return InterlockedIncrement(&this->ref_count);
};
virtual ULONG __stdcall Release( void )
{
ULONG nRefCount = InterlockedDecrement(&this->ref_count);
if ( nRefCount == 0 ) delete this;
return nRefCount;
};
virtual HRESULT __stdcall Read( void *pv, ULONG cb, ULONG *pcbRead )
{
EnterCriticalSection( &this->critical_section );
this->is.read( reinterpret_cast<char*>(pv), cb );
*pcbRead = static_cast<ULONG>( this->is.gcount() );
LeaveCriticalSection( &this->critical_section );
return S_OK;
};
virtual HRESULT __stdcall Write( void const *pv, ULONG cb, ULONG *pcbWritten )
{
*pcbWritten = cb;
return S_OK;
};
private:
istream &is;
CRITICAL_SECTION critical_section;
ULONG ref_count;
};
Вы должны реализоватькласс ISAXContentHandler тоже (конечно, вы должны заполнить методы, когда вам нужно):
class MyContentHandler : public ISAXContentHandler
{
public:
MyContentHandler( void )
: ref_count(0)
{};
virtual ~MyContentHandler( void ) {};
virtual HRESULT __stdcall QueryInterface( const IID &riid, void ** ppvObject )
{
if ( riid == __uuidof(ISAXContentHandler) )
{
*ppvObject = static_cast<void*>(this);
this->AddRef();
return S_OK;
}
if (riid == IID_IUnknown)
{
*ppvObject = static_cast<void*>(this);
this->AddRef();
return S_OK;
}
*ppvObject = 0;
return E_NOINTERFACE;
};
virtual ULONG __stdcall AddRef( void )
{
return InterlockedIncrement(&this->ref_count);
};
virtual ULONG __stdcall Release( void )
{
ULONG nRefCount = InterlockedDecrement(&this->ref_count);
if ( nRefCount == 0 ) delete this;
return nRefCount;
};
virtual HRESULT __stdcall putDocumentLocator( ISAXLocator * pLocator) { return S_OK; };
virtual HRESULT __stdcall startDocument( void ) { return S_OK; };
virtual HRESULT __stdcall endDocument( void ) { return S_OK; };
virtual HRESULT __stdcall startPrefixMapping( const wchar_t *pwchPrefix, int cchPrefix, const wchar_t *pwchUri, int cchUri ) { return S_OK; };
virtual HRESULT __stdcall endPrefixMapping( const wchar_t *pwchPrefix, int cchPrefix) { return S_OK; };
virtual HRESULT __stdcall startElement( const wchar_t *pwchNamespaceUri, int cchNamespaceUri, const wchar_t *pwchLocalName, int cchLocalName, const wchar_t *pwchQName, int cchQName, ISAXAttributes *pAttributes ) { return S_OK; };
virtual HRESULT __stdcall endElement( const wchar_t *pwchNamespaceUri, int cchNamespaceUri, const wchar_t *pwchLocalName, int cchLocalName, const wchar_t *pwchQName, int cchQName) { return S_OK; };
virtual HRESULT __stdcall characters( const wchar_t *pwchChars, int cchChars) { return S_OK; };
virtual HRESULT __stdcall ignorableWhitespace( const wchar_t *pwchChars, int cchChars) { return S_OK; };
virtual HRESULT __stdcall processingInstruction( const wchar_t *pwchTarget, int cchTarget, const wchar_t *pwchData, int cchData) { return S_OK; };
virtual HRESULT __stdcall skippedEntity( const wchar_t *pwchName, int cchName) { return S_OK; };
protected:
ULONG ref_count;
};
Тогда вы можете легко проанализировать поток:
bool ParseStream( istream &is )
{
if ( FAILED(CoInitialize(NULL)) )
return false;
ISAXXMLReader * reader = 0;
if ( FAILED( CoCreateInstance( __uuidof(SAXXMLReader60), NULL, CLSCTX_ALL, __uuidof(ISAXXMLReader),(void**) &reader ) ) )
{
CoUninitialize()
return false;
}
ISequentialStream * my_stream = new MySequentialStream(is);
ISAXContentHandler * content_handler = new MyContentHandler;
my_stream->AddRef();
content_handler->AddRef();
if ( FAILED( reader->putContentHandler( content_handler ) ) )
{
my_stream->Release();
content_handler->Release();
reader->Release();
return false;
}
VARIANT var;
var.vt = VT_UNKNOWN;
var.punkVal = my_stream;
VARIANT_BOOL success = FALSE;
bool value = SUCCEEDED( reader->parse( var ) );
my_stream->Release();
content_handler->Release();
reader->Release();
return ( value && ( success != VARIANT_FALSE ) );
}