2010-06-20 4 views
4

Je cherche un moyen d'analyser XML en C++ dans Windows et j'en ai trouvé quelques-uns comme MSXML, Xerces, TinyXml etc mais je me demande quel est le meilleur dans termes de performance et caractéristiques. Mes exigences sont qu'il doit être capable d'être lié statiquement ou avoir la source incluse dans le projet lui-même et ne doit pas nécessiter d'outils supplémentaires tels que boost. MSXML serait le choix évident car il s'agit d'une bibliothèque MS, mais il semble être une bibliothèque COM et plutôt alambiquée pour en tirer une quelconque utilité.Façons d'analyser XML en C++ (Win32)

Quelqu'un at-il des suggestions quant à quelque chose de rapide et simple à utiliser?

Merci, J

+0

avez-vous regardé vtd-xml? –

Répondre

4

j'ai utilisé libxml avec succès. L'API est un peu déroutante et compliquée, mais une fois que vous l'obtenez, cela fonctionne plutôt bien. En plus, il est bourré de fonctionnalités, donc si vous en avez besoin, allez avec libxml. Vous n'avez pas à vous soucier des binaires gonflés, car vous ne pouvez lier que les pièces dont vous avez besoin. Vous ne avez pas besoin d'inclure la libxml complète si vous avez besoin pour analyser xml et à ne pas utiliser les trucs de XPath par exemple

+0

Parfait! Je viens de vérifier libxml2 et c'est exactement ce que je cherche, je l'ai mis en marche en un rien de temps. Merci. – JWood

2

La meilleure bibliothèque que je l'ai utilisé et qui est tout à fait transparent en termes d'utilisation et de compréhension était pugixml.

Extrêmement léger, très rapide, flexible et pratique - à quoi d'autre peut-on s'attendre?

1

Le papa poids lourd de parseurs XML est Xerces
Un analyseur plus simple plus facile Expat il y a C++ wrappers autour.

Il existe de nombreux analyseurs XML.
Un rapide Google vous trouvera beaucoup.

2

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)); 
}