2010-06-20 33 views
4

我正在尋找一種解析Windows中C++的XML的方法,並且我發現了一些例如MSXML,Xerces,TinyXml等,但我想知道哪種方法最好性能和功能的條款。我的要求是它必須能夠靜態鏈接,或者將源代碼包含在項目本身中,並且不得要求任何其他工具,例如boost。 MSXML將是一個顯而易見的選擇,因爲它是一個MS庫,但它似乎是一個COM庫,並且相當複雜,以便實際使用它。解析C++中的XML的方法(Win32)

有沒有人有任何建議快速和簡單的使用?

感謝, Ĵ

+0

你看vtd-xml嗎? – 2010-08-08 23:09:58

回答

4

我使用的libxml成功。這個API有點令人困惑和複雜,但是一旦你得到它,它的工作效果會非常好。除了它充滿了功能,所以如果你需要,使用libxml。 你不必擔心膨脹的二進制文件,因爲你只能鏈接你需要的部分。你不需要包含完整的libxml如果你只需要解析XML和不使用XPath的東西例如

+0

完美!我剛剛檢出了libxml2,這正是我正在尋找的東西,我已經完成並立即運行。謝謝。 – JWood 2010-06-21 20:21:54

2

最好的圖書館,我已經使用,這是絕對透明在使用和理解方面是pugixml.

極其輕便,速度非常快,靈活方便 - 您還能期待什麼?

1

XML解析器的重量級爸爸是Xerces
更簡單更容易解析器ExpatC++ wrappers左右。

周圍有很多XML解析器。
一個快速谷歌會發現你很多。

2

由於所有受支持的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)); 
}