Comme toute version de Windows prise en charge (y compris Windows XP SP3) inclut MSXML 6.0, vous devez utiliser MS XML 6.0. Vous devez implémenter la classe ISAXContentHandler et généralement j'implémente une classe ISequentialStream.
mise en œuvre d'un ISequentialStream pour Parse:
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;
};
Vous devriez mettre en œuvre une classe ISAXContentHandler aussi (bien sûr vous devez remplir les méthodes quand vous avez besoin):
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;
};
Ensuite, vous pouvez facilement analyser un flux:
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));
}
avez-vous regardé vtd-xml? –