解析C++中的XML的方法(Win32)

问题描述:

我正在寻找一种解析Windows中C++的XML的方法,并且我发现了一些例如MSXML,Xerces,TinyXml等,但我想知道哪种方法最好性能和功能的条款。我的要求是它必须能够静态链接,或者将源代码包含在项目本身中,并且不得要求任何其他工具,例如boost。 MSXML将是一个显而易见的选择,因为它是一个MS库,但它似乎是一个COM库,并且相当复杂,以便实际使用它。解析C++中的XML的方法(Win32)

有没有人有任何建议快速和简单的使用?

感谢, Ĵ

+0

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

我使用的libxml成功。这个API有点令人困惑和复杂,但是一旦你得到它,它的工作效果会非常好。除了它充满了功能,所以如果你需要,使用libxml。 你不必担心膨胀的二进制文件,因为你只能链接你需要的部分。你不需要包含完整的libxml如果你只需要解析XML和不使用XPath的东西例如

+0

完美!我刚刚检出了libxml2,这正是我正在寻找的东西,我已经完成并立即运行。谢谢。 – JWood 2010-06-21 20:21:54

最好的图书馆,我已经使用,这是绝对透明在使用和理解方面是pugixml.

极其轻便,速度非常快,灵活方便 - 您还能期待什么?

+1

关心“......可能是最好最容易使用”的部分?试过他们,我想呢? – 2010-06-20 21:37:09

XML解析器的重量级爸爸是Xerces
更简单更容易解析器ExpatC++ wrappers左右。

周围有很多XML解析器。
一个快速谷歌会发现你很多。

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