我正在寻找一种在Windows中用C ++解析XML的方法,我发现了一些如MSXML,Xerces,TinyXml等,但我想知道哪个在性能和功能方面最好。我的要求是它必须能够静态链接或将源包含在项目本身中,并且不得要求任何其他工具,例如boost。 MSXML将是一个显而易见的选择,因为它是一个MS库,但它似乎是一个COM库,而且实际上可以从中获得任何用处。
有没有人对快速和简单易用的东西有任何建议?
谢谢, Ĵ
答案 0 :(得分:4)
我成功使用了libxml。 API有点令人困惑和复杂,但一旦你得到它它的效果非常好。除了它充满了功能,所以如果你需要它,请使用libxml。 你不必担心臃肿的二进制文件,因为你只能链接你需要的部分。如果你只需要解析xml并且不使用xpath的东西,你就不需要包含完整的libxml
答案 1 :(得分:2)
我使用过的最好的库,在使用和理解术语中绝对透明是pugixml.
非常轻巧,非常快速,灵活和方便 - 还有什么可以期待?
答案 2 :(得分: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 ) );
}
答案 3 :(得分:1)
答案 4 :(得分:1)
XML解析器的重量级爸爸是Xerces
一个更简单的解析器Expat周围有C++ wrappers。
周围有很多XML解析器 一个快速的谷歌会发现你很多。