解析C++中的XML的方法(Win32)
我正在寻找一种解析Windows中C++的XML的方法,并且我发现了一些例如MSXML,Xerces,TinyXml等,但我想知道哪种方法最好性能和功能的条款。我的要求是它必须能够静态链接,或者将源代码包含在项目本身中,并且不得要求任何其他工具,例如boost。 MSXML将是一个显而易见的选择,因为它是一个MS库,但它似乎是一个COM库,并且相当复杂,以便实际使用它。解析C++中的XML的方法(Win32)
有没有人有任何建议快速和简单的使用?
感谢, Ĵ
我使用的libxml成功。这个API有点令人困惑和复杂,但是一旦你得到它,它的工作效果会非常好。除了它充满了功能,所以如果你需要,使用libxml。 你不必担心膨胀的二进制文件,因为你只能链接你需要的部分。你不需要包含完整的libxml如果你只需要解析XML和不使用XPath的东西例如
完美!我刚刚检出了libxml2,这正是我正在寻找的东西,我已经完成并立即运行。谢谢。 – JWood 2010-06-21 20:21:54
关心“......可能是最好最容易使用”的部分?试过他们,我想呢? – 2010-06-20 21:37:09
由于所有受支持的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));
}
你看vtd-xml吗? – 2010-08-08 23:09:58