高效XML读写类

在处理XML文件时,经常需要一个能够快速读写数据的类。本文介绍的这个C++模板类,专注于信息管理而非验证,因此不需要其他组件即可使用。它的主要优势在于速度快,非常适合需要快速读写XML文件的场景。

与之相比,XMLDOM组件使用起来较为复杂,且速度较慢。在某些情况下,如果不需要验证XML文件,且文件内容为纯XML且不需要格式化,那么本文介绍的类将是一个不错的选择。

这个XML类是基于模板的。它需要支持两个方法:一个用于读取,一个用于写入。用户也可以从这个类派生出自己的读取或写入方法。

如果需要处理UTF-8格式的文本,那么在发送到XML类之前需要先进行转换。Unicode或ASCII格式是可以直接使用的,但其他格式需要在处理前进行转换。如果类需要管理UTF-8转换或其他类型的功能,这将影响其处理XML文件的速度。

使用XMLDOM之后创建了这个类。XML是一种非常有用的格式,用于存储信息。但是,如果每次处理XML都需要一个像XMLDOM这样的“大象”控件,那么这可能有点过于复杂。现在,使用XML变得非常简单,而且开销非常小(几乎没有)。

使用代码

这个类使用起来非常简单,但其内部实现是高级的。它使用了一些通用的集合类,以及CString类。不知道为什么MFC团队没有将CString构建为一个独立的类?随着时间的推移,可能会感到有点厌倦,因为只需要CString,但却不得不包含整个MFC。作者主要使用WTL和ATL,因此解决方案是创建自己的CString。作者也喜欢编写可移植的代码。

以下是一些示例代码:

class CXMLBuffer { public: CXMLBuffer() : m_uIndex(0) { } CXMLBuffer(CString string) : m_stringXML(string), m_uIndex(0) { } CString GetXML() { return m_stringXML; } void Write(const TCHAR* pszBuffer, UINT uCount, UINT* puCount) { m_uIndex += uCount; TCHAR* psz = m_stringXML.GetBuffer(m_uIndex + 1); psz = &psz[m_uIndex - uCount]; memcpy(psz, pszBuffer, uCount); psz[uCount] = '\0'; m_stringXML.ReleaseBuffer(); } UINT Read(TCHAR* pszBuffer, UINT uCount, UINT* puCount) { TCHAR* psz = m_stringXML.GetBuffer(0); if (uCount + m_uIndex > m_stringXML.GetLength()) { uCount = m_stringXML.GetLength() - m_uIndex; } memcpy(pszBuffer, &psz[m_uIndex], uCount); m_uIndex += uCount; if (puCount != NULL) { *puCount = uCount; } return uCount; } unsigned m_uIndex; CString m_stringXML; };

* 示例 1 * 提取文本中的单词并插入到XML缓冲区

void Cxml1Doc::OnSampleSurroundwords() { CString string, stringWord; reinterpret_cast(m_viewList.GetHead())->GetWindowText(string); if (string.IsEmpty()) { ::AfxMessageBox(_T("No text to surround, type some words"), MB_OK); return; } const TCHAR* pszPosition = string; CXMLBuffer Buffer; CXMLArchive ar(&Buffer, CXMLArchive::eWrite); ar << Child(_T("DOCUMENT")); while (*pszPosition) { if (*pszPosition <= ' ') { if (!stringWord.IsEmpty()) { ar << Child(_T("WORD")) << attribute(_T("LENGTH"), stringWord.GetLength()) << (const TCHAR*)stringWord << EndNode; } while (*pszPosition && *pszPosition <= ' ') pszPosition++; stringWord.Empty(); continue; } stringWord += *pszPosition; pszPosition++; } if (!stringWord.IsEmpty()) { ar << Child(_T("WORD")) << attribute(_T("LENGTH"), stringWord.GetLength()) << (const TCHAR*)stringWord << EndNode; } ar << End; ar.Flush(); reinterpret_cast(m_viewList.GetHead())->SetWindowText(Buffer.GetXML()); }

* 示例 2 * 向XML对象添加值

void Cxml1Doc::OnSampleHardcoded1() { CXMLBuffer Buffer; CXMLArchive ar(&Buffer, CXMLArchive::eWrite); ar << Child(_T("DOCUMENT")) << Child(_T("CHILD")) << attribute(_T("A1"), 1) << attribute(_T("A2"), 1.1) << attribute(_T("A3"), _T("TEXT")) << _T("Value") << EndNode << Child(_T("CHILD")) << attribute(_T("A1"), 1) << attribute(_T("A2"), 1.2) << attribute(_T("A3"), _T("TEXT")) << _T("Value") << Child(_T("CHILD")) << attribute(_T("A1"), 1) << attribute(_T("A2"), 1.3) << attribute(_T("A3"), _T("TEXT")) << _T("Value") << EndNode << EndNode; ar << End; reinterpret_cast(m_viewList.GetHead())->SetWindowText(Buffer.GetXML()); }

* 示例 3 * 展示如何从格式化的XML文本中读取

void Cxml1Doc::OnSampleReadtext() { TCHAR* pszText = _T("") _T("Item value") _T("Item value") _T("") _T("xxxxxxxx") _T("") _T(""); CString stringReport; CXMLBuffer Buffer(pszText); CXMLArchive ar(&Buffer); while (ar.ReadNext() == true) { if (!ar.IsEndTag()) { CString stringName = (const TCHAR*)ar.GetName(); stringReport += stringName; stringReport += _T("\r\n"); if (stringName == _T("ITEM")) { ar.PreReadNext(); CString stringNextName = (const TCHAR*)ar.GetNextName(); if (stringNextName == _T("CHILDITEM")) { stringReport += _T("Next item is named CHILDITEM."); if (!ar.HasNextChildren()) { stringReport += _T("And that item doesn't have any children."); } stringReport += _T("\r\n"); } } } } reinterpret_cast(m_viewList.GetHead())->SetWindowText(stringReport); }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485