简体   繁体   English

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

[英]Ways to parse XML in C++ (Win32)

I'm looking for a way to parse XML in C++ in Windows and I've found a few such as MSXML, Xerces, TinyXml etc but I'm wondering which is best in terms of performance and features. 我正在寻找一种在Windows中用C ++解析XML的方法,我发现了一些如MSXML,Xerces,TinyXml等,但我想知道在性能和功能方面哪个最好。 My requirements are that it must be able to be static linked or have the source included in the project itself and must not require any additional toolits such as boost. 我的要求是它必须能够静态链接或将源包含在项目本身中,并且不得要求任何其他工具,例如boost。 MSXML would be the obvious choice as it's an MS library but it seems to be a COM library and rather convoluted to actually get any use out of it. MSXML将是一个显而易见的选择,因为它是一个MS库,但它似乎是一个COM库,而且实际上可以从中获得任何用处。

Does anyone have any suggestions as to something quick and simple to use? 有没有人对快速和简单的使用有什么建议?

Thanks, J 谢谢,J

I used libxml with success. 我成功使用了libxml。 The API is a bit confusing and complicated, but once you get it it works pretty good. API有点令人困惑和复杂,但一旦你得到它它的效果非常好。 Besides it is stuffed with functionality, so if you need that, go with libxml. 除了它充满了功能,所以如果你需要它,请使用libxml。 You dont have to worry about bloated binaries since you can only link the parts you need. 你不必担心臃肿的二进制文件,因为你只能链接你需要的部分。 You dont need to include the complete libxml if you only need to parse xml and dont use the xpath stuff for example 如果你只需要解析xml并且不使用xpath的东西,你就不需要包含完整的libxml

The best library that I've used and which is absolutely transparent in usage and understanding terms was pugixml. 我使用过的最好的库,在使用和理解术语上绝对透明pugixml。

Extremely lightweight, very fast, flexible and convenient - what else could one expect? 非常轻巧,非常快速,灵活和方便 - 还有什么可以期待的?

Since all supported Windows version (including Windows XP SP3) includes MSXML 6.0, you should use MS XML 6.0. 由于所有受支持的Windows版本(包括Windows XP SP3)都包含MSXML 6.0,因此应使用MS XML 6.0。 You should implement own ISAXContentHandler class and usually I implement an ISequentialStream class. 您应该实现自己的ISAXContentHandler类,通常我实现一个ISequentialStream类。

An ISequentialStream implementation for parse: 解析的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;
};

You should implement an ISAXContentHandler class, too (of course you should fill the methods when you needed): 您也应该实现一个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;
};

Then you could easily parse a stream: 然后你可以轻松解析一个流:

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

The heavyweight daddy of XML parsers is Xerces XML解析器的重量级爸爸是Xerces
A simpler easier parser Expat there are C++ wrappers around. 一个更简单的解析器ExpatC ++包装器

There are a lot of XML parsers around. 有很多XML解析器。
A quick Google will find you plenty. 一个快速的谷歌会发现你很多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM