用于存储或加载信息的 XML 类





5.00/5 (4投票s)
2002年10月26日
3分钟阅读

186922

2706
序列化 XML 中存储的信息
引言
本文介绍了一个用于读写以 XML 格式存储信息的类。主要任务是管理信息,而不是验证。使用这个类不需要其他组件。它非常快,这也是它的主要目的,尽可能快地读写 XML。
XMLDOM
组件使用起来更困难,而且慢得多。有时候,你不需要验证 XML,XML 文件只是纯 XML,并且没有进行格式化。那么,我想你会喜欢它。
在可下载文件中,有一个帮助文件 (CHM) 描述了方法。该文件是使用 doxygen 完成的。帮助文件中也有关于如何使用它的小样本。
XML 类是基于模板的。被包装的类需要支持两种方法,一种用于读取,一种用于写入。也可以从该类派生并创建你自己的读取或写入方法。
如果你正在读取 UTF-8 格式的文本,那么你需要先将其转换,然后再发送给 XML 类。Unicode 或 ASCII 没问题,但其他格式需要在处理前进行转换。如果该类应该具有 UTF-8 转换或其他类型的功能,而这些功能对于将信息流传输到 XML 文件或从 XML 文件流传输信息并不是真正需要的,那么这将影响速度。
它还使用缓冲读取或写入。信息块分段完成。我将尝试在此处更新代码以添加新功能或添加其他类型的代码。但是如果你需要最新的,请访问 Gorep Development。
注意:本文随附的代码旨在有效使用,而不仅仅是为了教程。
背景
在使用了 XMLDOM
之后,我创建了这个类。当需要存储信息时,XML 是一种非常有用的格式。但是,如果有一个像 XMLDOM
这样的“庞大”控件,每次需要处理 XML 时都需要它,那么这可能有点过分了。现在使用 XML 是一项非常简单的任务,而代价非常小(开销很小)。
Using the Code
这个类真的很容易使用,但内部是高级的。它使用一些包含的通用集合类。还有 CString
类。不知道为什么 MFC 团队没有将 CString
构建为一个独立的类??随着时间的推移,你将会厌倦只包含 MFC,仅仅因为你需要 CString
。我主要使用 WTL 和 ATL,所以解决方案是创建我自己的 CString
。此外,我喜欢编写可移植的代码 ;-)。
如果你对新的或改进的功能有任何愿望,请不要犹豫,提出要求。我会尝试添加它(如果它不影响速度)。
以下是来自下载演示的一些示例代码
// class used for reading and writing
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;
};
using namespace gd_xml_stream;
/**
* SAMPLE 1
* Extract words from text and insert them to XML buffer
*/
void Cxml1Doc::OnSampleSurroundwords()
{
CString string, stringWord;
reinterpret_cast<CEditView*>
(m_viewList.GetHead())->GetWindowText( string );
if( string.IsEmpty() )
{
::AfxMessageBox( _T("No text to surround, type som words"), MB_OK );
return;
} // if( string.IsEmpty() ){
const TCHAR* pszPosition = string;
CXMLBuffer Buffer;
CXMLArchive<CXMLBuffer> ar( &Buffer,
CXMLArchive<CXMLBuffer>::eWrite );
ar << Child << _T("DOCUMENT");
while( *pszPosition )
{
if( *pszPosition <= ' ' )
{
if( stringWord.IsEmpty() == false )
{
ar << Child << _T("WORD") <<
attribute( _T("LENGTH"), stringWord.GetLength() )
<< (const TCHAR*)stringWord << EndNode;
}
while( *pszPosition && *pszPosition <= ' ' ) pszPosition++;
stringWord.Empty();
continue;
}
stringWord += *pszPosition;
pszPosition++;
} // while( *pszPosition ){
if( stringWord.IsEmpty() == false )
{
ar << Child << _T("WORD") << attribute( _T("LENGTH"),
stringWord.GetLength() )
<< (const TCHAR*)stringWord << EndNode;
}
ar << End;
ar.Flush();
reinterpret_cast<CEditView*>
(m_viewList.GetHead())->SetWindowText( Buffer.GetXML() );
}
/**
* SAMPLE 2
* Add values to XML object
*/
void Cxml1Doc::OnSampleHardcoded1()
{
CXMLBuffer Buffer;
CXMLArchive<CXMLBuffer> ar( &Buffer,
CXMLArchive<CXMLBuffer>::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<CEditView*>
(m_viewList.GetHead())->SetWindowText( Buffer.GetXML() );
}
/**
* SAMPLE 3
* Show how it is possible to read from XML formatted text.
*/
void Cxml1Doc::OnSampleReadtext()
{
TCHAR* pszText =
_T("<DOCUMENT>")
_T("<ITEM A1=\"Attribute value\">Item value</ITEM>")
_T("<ITEM A1=\"Attribute value\">Item value</ITEM>")
_T("<ITEM A1=\"Attribute value\">")
_T("<CHILDITEM A1=\"Attribute value\">xxxxxxxx</CHILDITEM>")
_T("</ITEM>")
_T("</DOCUMENT>");
CString stringReport;
CXMLBuffer Buffer( pszText );
CXMLArchive<CXMLBuffer> ar( &Buffer );
while( ar.ReadNext() == true )
{
if( ar.IsEndTag() == false )
{
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() == false )
{
stringReport +=
_T(" And that item don't have any childrens");
}
stringReport += _T("\r\n");
}
}
}
}
reinterpret_cast<CEditView*>
(m_viewList.GetHead())->SetWindowText( stringReport );
}
历史
感谢 Stephan Rodriguez 指出了与 VC 6.0 的兼容性问题。在他的帮助下,现在它应该可以与 VC 6.0 配合使用(我自己没有 VC 6.0)。
添加了用于保存文件和转换为 UTF8 的类的示例。
许可证
本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。
作者可能使用的许可证列表可以在此处找到。