65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIconstarIcon

5.00/5 (4投票s)

2002年10月26日

3分钟阅读

viewsIcon

186922

downloadIcon

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 的类的示例。

许可证

本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。

作者可能使用的许可证列表可以在此处找到。

© . All rights reserved.