[c++]一个对MSXML的封装类 使用C++的Smart Pointer 对MSXML DOM封装,可以方便地访问xml文件

来源:互联网 发布:怪物猎人p3数据库安卓 编辑:程序博客网 时间:2024/04/29 17:28

#pragma once
#include "XmlNode.h"


//-------------------------------------------------------------------------
// Classes Name     :CXml CXmlNode CXmlNodes
// Author   :王嘉 QQ32775973 sky-sea-earth@21cn.com
// CreateTime       :2005-10-23
// Memo             :Xml结点类库
// Version          :v1.4
// Modify   :v.1.3
//     : 修改了几个Bug
//     :v.1.4
//     : 增加了异常处理
//     : 加入了Base64编码
//     : 更新的例子程序
//     : 增加了一个Unicode版本
//     : 改写部分代码 让它和VC6兼容
//-------------------------------------------------------------------------

class CXml
{
public:
 CXml(void);
 ~CXml(void);

protected:
 MSXML2::IXMLDOMDocument2Ptr m_pDoc;
 CString      m_strFilePath;

public:
 // 打开Xml文件
 BOOL Open(CString strXmlFilePath);

 // 保存Xml文件
 BOOL Save(LPCTSTR lpszFilePath = NULL);

 // 关闭Xml文件
 void Close(void);

 // 获取最近的错误信息
 CString GetLastError(void);

 // 获取Xml树的根结点
 CXmlNodePtr GetRoot(void);  

 // 选择单个结点
 CXmlNodePtr SelectSingleNode(LPCTSTR lpszPath);

 // 选择结点集合
 CXmlNodesPtr SelectNodes(LPCTSTR lpszPath);

 // 判断文件是否存在
 static BOOL IsFileExist(CString strFilePath);

 // 创建结点
 CXmlNodePtr CreateNode(CString strName);

 // Base64编码解码
 BOOL Base64Decode( CString strIn, LPBYTE & pBuf, LONG & lSize);
 CString Base64Encode( LPBYTE pBuf, ULONG ulSize);
};

#include "StdAfx.h"
#include "./xml.h"


CXml::CXml(void)
: m_strFilePath(_T(""))
, m_pDoc(NULL)
{
}

CXml::~CXml(void)
{
 Close();
}


//-------------------------------------------------------------------------
// Function Name    :IsFileExist [static]
// Parameter(s)     :CString strFilePath 文件路径和名称
// Return           :BOOL
// Memo             :判断文件是否存在
//-------------------------------------------------------------------------
BOOL CXml::IsFileExist(CString strFilePath)
{
 BOOL bExist = FALSE;
 HANDLE hFile = NULL;

 hFile = CreateFile( strFilePath
  , GENERIC_READ
  , FILE_SHARE_READ | FILE_SHARE_WRITE
  , NULL
  , OPEN_EXISTING
  , 0
  , 0
  );

 if( hFile != INVALID_HANDLE_VALUE )
 {
  CloseHandle( hFile );
  bExist = TRUE;
 }

 return (bExist);
}


//-------------------------------------------------------------------------
// Function Name    :CreateNode
// Parameter(s)     :CString strName 结点名称
// Return           :CXmlNodePtr
// Memo             :创建结点
//-------------------------------------------------------------------------
CXmlNodePtr CXml::CreateNode(CString strName)
{
 ASSERT( m_pDoc != NULL );

 CXmlNodePtr pChild( new CXmlNode() );
 
 try
 { MSXML2::IXMLDOMNodePtr pChildNode = NULL;
  pChildNode = m_pDoc->createElement( _bstr_t(strName) );
  ASSERT( pChildNode != NULL );
  pChild->m_pNode = pChildNode;
  RELEASE_PTR(pChildNode);
 }
 catch ( _com_error e )
 {
  TRACE( _T("CXml::CreateNode 发生异常:%s/n"), e.ErrorMessage());
  ASSERT( FALSE );
 }
 return pChild;
}

//-------------------------------------------------------------------------
// Function Name    :Open
// Parameter(s)     :CString strXmlFilePath 文件路径和名称
// Return           :BOOL 是否成功
// Memo             :打开XML文件 如果不存在则创建之
//-------------------------------------------------------------------------
BOOL CXml::Open( CString strXmlFilePath )
{
 HRESULT hr = S_OK;

 hr = m_pDoc.CreateInstance( __uuidof(MSXML2::DOMDocument40) );
 if( !SUCCEEDED(hr) )
 {
  ASSERT(FALSE); // did u CoInitialize ? did u install MSXML4.0 ?
  return FALSE;
 }

 m_strFilePath = strXmlFilePath;
 VARIANT_BOOL vbSuccessful = VARIANT_TRUE;

 try
 {
  m_pDoc->preserveWhiteSpace = VARIANT_FALSE;
  m_pDoc->validateOnParse = VARIANT_FALSE;
  m_pDoc->setProperty( "NewParser", true);

  if( IsFileExist(strXmlFilePath) )
  {
   vbSuccessful = m_pDoc->load( COleVariant((LPCTSTR)strXmlFilePath) );
  }
  else
  {
   MSXML2::IXMLDOMProcessingInstructionPtr pPI = NULL;
   pPI = m_pDoc->createProcessingInstruction( _bstr_t(_T("xml")), _bstr_t(_T("version=/"1.0/"")) );
   ASSERT( pPI != NULL );

   hr = m_pDoc->appendChild(pPI);
   ASSERT( SUCCEEDED(hr) );

   // 创建根节点
   MSXML2::IXMLDOMElementPtr pRoot = NULL;
   pRoot = m_pDoc->createElement( _bstr_t(_T("xmlRoot")) );
   m_pDoc->appendChild(pRoot);
   RELEASE_PTR(pRoot);

   vbSuccessful = SUCCEEDED(hr) ? VARIANT_TRUE : VARIANT_FALSE;
  }// if_else
 }
 catch(...)
 {
  vbSuccessful = FALSE;
  ASSERT( FALSE );
 }

 return vbSuccessful;
}


//-------------------------------------------------------------------------
// Function Name    :Close
// Parameter(s)     :void
// Return           :void
// Memo             :关闭
//-------------------------------------------------------------------------
void CXml::Close(void)
{
 RELEASE_PTR(m_pDoc);
}

//-------------------------------------------------------------------------
// Function Name    :GetLastError
// Parameter(s)     :void
// Return           :CString
// Memo             :获取最后的出错信息
//-------------------------------------------------------------------------
CString CXml::GetLastError(void)
{
 ASSERT( m_pDoc != NULL );

 HRESULT hr = S_OK;
 MSXML2::IXMLDOMParseErrorPtr pIParseError = NULL;

 hr = m_pDoc->get_parseError(&pIParseError);
 ASSERT( SUCCEEDED(hr) );

 CString strRet;
 if( pIParseError != NULL )
 {
  BSTR bstr = NULL;
        hr = pIParseError->get_reason(&bstr);
  ASSERT( SUCCEEDED(hr) );

  strRet = (LPCTSTR)_bstr_t( bstr, true);

  if( bstr != NULL )
  {
   SysFreeString(bstr);
   bstr = NULL;
  }

  RELEASE_PTR(pIParseError);  
 }

 return strRet;
}

//-------------------------------------------------------------------------
// Function Name    :GetRoot
// Parameter(s)     :
// Return           :
// Memo             :获取根节点
//-------------------------------------------------------------------------
CXmlNodePtr CXml::GetRoot(void)

 ASSERT( m_pDoc != NULL );

 CXmlNodePtr pNode( new CXmlNode() );

 try
 {
  MSXML2::IXMLDOMElementPtr pElement = NULL;
  HRESULT hr = m_pDoc->get_documentElement(&pElement);
  ASSERT( SUCCEEDED(hr) );
  ASSERT( pElement != NULL );

  pNode->m_pNode = pElement;
  RELEASE_PTR(pElement);
 }
 catch ( _com_error e )
 {
  TRACE( _T("CXml::GetRoot 发生异常:%s/n"), e.ErrorMessage());
  ASSERT( FALSE );
 }
 
 return pNode;
}

//-------------------------------------------------------------------------
// Function Name    :Save
// Parameter(s)     :LPCTSTR lpszFilePath [in] 保存的位置
// Return           :BOOL
// Memo             :保存Xml文件
//-------------------------------------------------------------------------
BOOL CXml::Save(LPCTSTR lpszFilePath /* = NULL */)
{
 ASSERT( m_pDoc != NULL ); 

 HRESULT hr = S_OK; 
 try
 {
  if( lpszFilePath == NULL )
   hr = m_pDoc->save( COleVariant((LPCTSTR)m_strFilePath) );
  else
   hr = m_pDoc->save( _variant_t( lpszFilePath ) );
 }
 catch( _com_error e )
 {
  TRACE( _T("CXml::Save 发生异常:%s/n"), e.ErrorMessage());
  ASSERT( FALSE );
  return FALSE;
 }
 

 return SUCCEEDED(hr);
}

//-------------------------------------------------------------------------
// Function Name    :SelectSingleNode
// Parameter(s)     :LPCTSTR strPath  路径名
// Return           :CXmlNodePtr
// Memo             :取单个节点
//-------------------------------------------------------------------------
CXmlNodePtr CXml::SelectSingleNode(LPCTSTR lpszPath)
{
 ASSERT( m_pDoc != NULL );

 CXmlNodePtr pNode ( new CXmlNode() );

 if( !GetRoot()->IsNull() )
  (*pNode) = GetRoot()->SelectSingleNode(lpszPath);
 
 return pNode;
}

//-------------------------------------------------------------------------
// Function Name    :SelectNodes
// Parameter(s)     :LPCTSTR strPath 路径名
// Return           :CXmlNodesPtr
// Memo             :取结点集合
//-------------------------------------------------------------------------
CXmlNodesPtr CXml::SelectNodes(LPCTSTR lpszPath)
{
 ASSERT( m_pDoc != NULL );

 CXmlNodesPtr pNodes( new CXmlNodes() );

 if( !GetRoot()->IsNull() )
  (*pNodes) = GetRoot()->SelectNodes(lpszPath);

    return pNodes;
}

//-------------------------------------------------------------------------
// Function Name    :EncodeBase64
// Parameter(s)     :LPBYTE *pBuf 首地址
//     :ULONG ulSize 大小
// Return           :CString  编码后的结果
// Memo             :堆二进制数据编码成Base64格式
//-------------------------------------------------------------------------
CString CXml::Base64Encode(LPBYTE pBuf, ULONG ulSize)
{
 ASSERT( m_pDoc != NULL );
 ASSERT( pBuf != NULL );
 
 CString strRet = _T("");
 try
 {
  MSXML2::IXMLDOMElementPtr pElement = NULL;
  pElement = m_pDoc->createElement( _bstr_t(_T("Base64")) );
  ASSERT( pElement != NULL );

  HRESULT hr = S_OK;
  hr = pElement->put_dataType( _bstr_t(_T("bin.base64")) );
  ASSERT( SUCCEEDED(hr) );

  SAFEARRAY * pAry = SafeArrayCreateVector( VT_UI1, 0L, ulSize);
  ::memcpy( pAry->pvData, pBuf, ulSize);

  VARIANT var;
        VariantInit(&var);
        var.parray = pAry;
        var.vt = VT_ARRAY | VT_UI1;
        pElement->nodeTypedValue = var;

  BSTR bstr = NULL;
  hr = pElement->get_text( &bstr );
  ASSERT( SUCCEEDED(hr) ); 
  strRet = (LPCTSTR)_bstr_t( bstr, true);

  if( bstr != NULL )
  {
   SysFreeString(bstr);
   bstr = NULL;
  }

  RELEASE_PTR(pElement);
 }
 catch ( _com_error e )
 {
  TRACE( _T("CXml::Base64Encode 发生异常:%s/n"), e.ErrorMessage());
  ASSERT( FALSE );
 }

 return strRet;
}

//-------------------------------------------------------------------------
// Function Name    :Base64Decode
// Parameter(s)     :CString strIn Base64编码
//     :LPBYTE pBuf 缓冲区首地址
//     :ULONG &ulSize 缓冲区大小
// Return           :BOOL
// Memo             :将Base64编码解码为二进制形式
//     注意!此函数的缓冲区需要在函数调用完后删除
//-------------------------------------------------------------------------
BOOL CXml::Base64Decode(CString strIn, LPBYTE & pBuf, LONG &lSize)
{
 ASSERT( m_pDoc != NULL );
 
 try
 {
  MSXML2::IXMLDOMElementPtr pElement = NULL;
  pElement = m_pDoc->createElement( _bstr_t(_T("Base64")) );
  ASSERT( pElement != NULL );

  HRESULT hr = S_OK;
  hr = pElement->put_dataType( _bstr_t(_T("bin.base64")) );
  ASSERT( SUCCEEDED(hr) );

  hr = pElement->put_text( CComBSTR(strIn) );
  ASSERT( SUCCEEDED(hr) );

        hr = SafeArrayGetUBound( pElement->nodeTypedValue.parray, 1, &lSize);
  ASSERT( SUCCEEDED(hr) );
  lSize ++;

  pBuf = new BYTE[lSize];
  memset( pBuf, 0, lSize);

  memcpy( pBuf, LPVOID(pElement->nodeTypedValue.parray->pvData), lSize); 

  RELEASE_PTR(pElement);
 }
 catch ( _com_error e )
 {
  TRACE( _T("CXml::Base64Decode 发生异常:%s/n"), e.ErrorMessage());
  ASSERT( FALSE );
  return FALSE;
 }
 
 return TRUE;
}

#pragma once

#import "msxml4.dll"
#include
#include

#ifndef RELEASE_PTR
#define RELEASE_PTR(x) /
 if( x != NULL )  /
 {     /
  x.Release(); /
  x = NULL;  /
 }
#endif

class CXml;
class CXmlNode;
class CXmlNodes;

typedef std::auto_ptr  CXmlNodePtr;
typedef std::auto_ptr  CXmlNodesPtr;

//////////////////////////////////////////////////////////////////////////

#include "./XmlNodes.h"

class CXmlNode
{
 friend class CXml;
 friend class CXmlNode;
 friend class CXmlNodes;

protected:
 
 MSXML2::IXMLDOMNodePtr  m_pNode;
 
 CXmlNode( MSXML2::IXMLDOMNodePtr pNode);

 BOOL _GetValue(CString & strValue);
 BOOL _SetValue(CString & strValue);

 BOOL _GetAttribute( CString & strName, CString & strValue);
 BOOL _SetAttribute( CString & strName, CString & strValue);

public:

 //   _______________
 //______| 构造析构 |___________________________________________________________________
 CXmlNode(void);
 CXmlNode( CXmlNode & refNode IN);
 ~CXmlNode(void);


 //   _______________
 //______| 重载 = 号 |___________________________________________________________________
 CXmlNodePtr operator = ( CXmlNodePtr pNode);
 CXmlNode & operator = ( CXmlNode & refNode);

 BOOL IsNull(void);   // 当前结点是否为空
 CString GetName(void);  // 获取当前结点名称
 CXmlNode & Remove(void); // 将结点与父结点分离
 void Release(void);;  // 释放节点


 //   _______________
 //______| 父子操作 |___________________________________________________________________
 CXmlNodePtr GetChild( CString strName, BOOL bBuildIfNotExist = TRUE);
 CXmlNodePtr NewChild( CString strName );
 CXmlNodePtr GetParent(void);
 CXmlNodesPtr GetChildren();
 void AddChild( CXmlNodePtr & pChildNode);
 void AddChild( CXmlNode & refChildNode);
 BOOL HasChildren(void);
 BOOL RemoveChildren(void);

 //   _______________
 //______| 属性操作 |___________________________________________________________________
 CString GetAttribute( CString strName, LPCTSTR lpszDefault = NULL);
 bool GetAttribute( CString strName, bool bDefault); 
 int  GetAttribute( CString strName, int nDefault); 
 float GetAttribute( CString strName, float fDefault); 
 double GetAttribute( CString strName, double dDefault);

 BOOL SetAttribute( CString strName, LPCTSTR lpszValue);
 BOOL SetAttribute( CString strName, bool bValue);
 BOOL SetAttribute( CString strName, int nValue);
 BOOL SetAttribute( CString strName, float fValue);
 BOOL SetAttribute( CString strName, double dValue);

 BOOL RemoveAttribute( CString strName );


 //   _______________
 //______| 值操作  |___________________________________________________________________ 
 CString GetValue( LPCTSTR lpszDefault = NULL );
 bool GetValue( bool bDefault );
 int  GetValue( int nDefault);
 float GetValue( float fDefault);
 double GetValue( double dDefault);

 BOOL SetValue( LPCTSTR lpszValue );
 BOOL SetValue( bool bValue );
 BOOL SetValue( int nValue );
 BOOL SetValue( float fValue );
 BOOL SetValue( double dValue );


 //   _______________
 //______| XPath查询 |___________________________________________________________________
 CXmlNodePtr SelectSingleNode(LPCTSTR lpszPath);
 CXmlNodesPtr SelectNodes(LPCTSTR lpszPath);


};

#include "StdAfx.h"
#include "./xmlnode.h"


//////////////////////////////////////////////////////////////////////////
#ifndef _tstof
 #ifdef _UNICODE

  double __cdecl _tstof( const wchar_t *ptr )
  {
      CHAR astring[20];
   WideCharToMultiByte( CP_ACP, 0, ptr, -1, astring, 20, NULL, NULL);
   return atof(astring);
  }

 #else
  #define _tstof atof
 #endif
#endif
//////////////////////////////////////////////////////////////////////////

//-------------------------------------------------------------------------
// Function Name    :_GetValue
// Parameter(s)     :CString & strValue IN 值
// Return           :BOOL 是否成功
// Memo             :获取当前节点的值
//-------------------------------------------------------------------------
BOOL CXmlNode::_GetValue(CString & strValue OUT)
{
 ASSERT( m_pNode != NULL );

 HRESULT hr = S_OK;
 try
 {
  if( HasChildren() )
  {
   // 下面有子结点
   ASSERT( FALSE );
   return FALSE;
  }

  BSTR bstr = NULL;
  hr = m_pNode->get_text( &bstr );
  ASSERT( SUCCEEDED(hr) ); 
  strValue = (LPCTSTR)_bstr_t( bstr, true);

  if( bstr != NULL )
  {
   SysFreeString(bstr);
   bstr = NULL;
  }
 }
 catch ( _com_error e )
 {
  TRACE( _T("CXmlNode::_GetValue 发生异常:%s/n"), e.ErrorMessage());
  ASSERT( FALSE );
  return FALSE;
 }
 
 return SUCCEEDED(hr);
}

//-------------------------------------------------------------------------
// Function Name    :_SetValue
// Parameter(s)     :CString & strValue IN
// Return           :BOOL 是否成功
// Memo             :获取当前节点的值
//-------------------------------------------------------------------------
BOOL CXmlNode:: _SetValue(CString & strValue IN)
{
 ASSERT( m_pNode != NULL );

 HRESULT hr = S_OK;

 try
 {
  if( HasChildren() )
  {
   // 下面有子结点
   ASSERT( FALSE );
   return FALSE;
  }

  hr = m_pNode->put_text( CComBSTR(strValue) );
  ASSERT( SUCCEEDED(hr) );
 }
 catch ( _com_error e )
 {
  TRACE( _T("CXmlNode::_SetValue 发生异常:%s/n"), e.ErrorMessage());
  ASSERT( FALSE );
  return FALSE;
 }
 return SUCCEEDED(hr);
}

//-------------------------------------------------------------------------
// Function Name    :_GetAttribute
// Parameter(s)     :CString & strName IN 属性名
// Return   :CString & strValue OUT 属性值
// Memo             :获取属性值
//-------------------------------------------------------------------------
BOOL CXmlNode::_GetAttribute( CString & strName IN, CString & strValue OUT)
{
 ASSERT( m_pNode != NULL );

 HRESULT hr = S_OK;

 try
 {
  MSXML2::IXMLDOMNamedNodeMapPtr pIXMLDOMNamedNodeMap = NULL;
  hr = m_pNode->get_attributes(&pIXMLDOMNamedNodeMap);
  if( !SUCCEEDED(hr) )
  {
   ASSERT( FALSE );
   return FALSE;
  }

  MSXML2::IXMLDOMNodePtr pIXMLDOMNode = NULL;
  pIXMLDOMNode = pIXMLDOMNamedNodeMap->getNamedItem( _bstr_t(strName) );

  if( pIXMLDOMNode == NULL )
  {
   strValue.Empty();
  }
  else
  {
   VARIANT varValue;
   hr = pIXMLDOMNode->get_nodeValue(&varValue);
   if( !SUCCEEDED(hr) )
   {
    ASSERT( FALSE );
    return FALSE;
   }

   strValue = (LPCTSTR)(_bstr_t)varValue;
  }

  RELEASE_PTR(pIXMLDOMNode);
  RELEASE_PTR(pIXMLDOMNamedNodeMap);
 }
 catch ( _com_error e )
 {
  TRACE( _T("CXmlNode::_GetAttribute 发生异常:%s/n"), e.ErrorMessage());
  ASSERT( FALSE );
  return FALSE;
 }

 return TRUE;
}


//-------------------------------------------------------------------------
// Function Name    :_SetAttribute
// Parameter(s)     :CString & strName IN 名称
//     :CString & strValue IN  属性值
// Return           :BOOL
// Memo             :设置属性值
//-------------------------------------------------------------------------
BOOL CXmlNode::_SetAttribute( CString & strName, CString & strValue IN)
{
 ASSERT( m_pNode != NULL );

 HRESULT hr = S_OK;
 try
 {
  MSXML2::IXMLDOMElementPtr pElement = NULL;
  pElement = static_cast (m_pNode);
  hr = pElement->setAttribute( (_bstr_t)CComBSTR(strName), _variant_t((LPCTSTR)strValue) );
  RELEASE_PTR(pElement);
 }
 catch ( _com_error e )
 {
  TRACE( _T("CXmlNode::_SetAttribute 发生异常:%s/n"), e.ErrorMessage());
  ASSERT( FALSE );
  return FALSE;
 }

 return SUCCEEDED(hr);
}

//-------------------------------------------------------------------------
// Function Name    :CXmlNode
// Parameter(s)     :MSXML2::IXMLDOMNodePtr pNode [in]
// Memo             :构造器
//-------------------------------------------------------------------------
CXmlNode::CXmlNode( MSXML2::IXMLDOMNodePtr pNode IN)
{
 m_pNode = pNode;
}


//-------------------------------------------------------------------------
// Function Name    :CXmlNode
// Parameter(s)     :void
// Memo             :构造器
//-------------------------------------------------------------------------
CXmlNode::CXmlNode(void)
{
 m_pNode = NULL; 
}


//-------------------------------------------------------------------------
// Function Name    :CXmlNode
// Parameter(s)     :CXmlNode & refNode [in]
// Memo             :拷贝构造函数
//-------------------------------------------------------------------------
CXmlNode::CXmlNode( CXmlNode & refNode IN)
{
 m_pNode = refNode.m_pNode;
}


//-------------------------------------------------------------------------
// Function Name    :~CXmlNode
// Parameter(s)     :void
// Memo             :析构函数
//-------------------------------------------------------------------------
CXmlNode::~CXmlNode(void)
{
 RELEASE_PTR(m_pNode);
}


//-------------------------------------------------------------------------
// Function Name    :Release
// Parameter(s)     :void
// Return           :void
// Memo             :释放节点
//-------------------------------------------------------------------------
void CXmlNode::Release(void)
{
 RELEASE_PTR(m_pNode);
}


//-------------------------------------------------------------------------
// Function Name    :operator =
// Parameter(s)     :CXmlNodePtr pNode [in]
// Return           :CXmlNodePtr
// Memo             :重载 = 操作符
//-------------------------------------------------------------------------
CXmlNodePtr CXmlNode::operator = ( CXmlNodePtr pNode IN)
{
 RELEASE_PTR(m_pNode);

 m_pNode = pNode->m_pNode;
 return pNode;
}


//-------------------------------------------------------------------------
// Function Name    :operator =
// Parameter(s)     :CXmlNode & refNode [in]
// Return           :CXmlNode &
// Memo             :重载 = 操作符
//-------------------------------------------------------------------------
CXmlNode & CXmlNode::operator = ( CXmlNode & refNode IN)
{
 RELEASE_PTR(m_pNode);

 m_pNode = refNode.m_pNode;
 return (*this);
}


//-------------------------------------------------------------------------
// Function Name    :IsNull
// Parameter(s)     :void
// Return           :BOOL
// Memo             :判断此结点是否是空节点
//-------------------------------------------------------------------------
BOOL CXmlNode::IsNull(void)
{
 return m_pNode == NULL;
}

//-------------------------------------------------------------------------
// Function Name    :GetChild
// Parameter(s)     :CString strName  节点名称
//     :BOOL bBuildIfNotExist 不存在则创建?
// Return           :儿子节点指针
// Memo             :获取儿子
//-------------------------------------------------------------------------
CXmlNodePtr CXmlNode::GetChild( CString strName, BOOL bBuildIfNotExist /* = TRUE */)
{
 ASSERT( m_pNode != NULL );

 CXmlNodePtr pChild( new CXmlNode() );

 try
 {
  MSXML2::IXMLDOMNodePtr pChildNode = NULL;
  pChildNode = m_pNode->selectSingleNode(_bstr_t((LPCTSTR)strName));

  // 不存在 则 创建
  if( pChildNode == NULL && bBuildIfNotExist )
  {
   MSXML2::IXMLDOMDocumentPtr pDoc = NULL;
   HRESULT hr = m_pNode->get_ownerDocument(&pDoc);
   ASSERT( SUCCEEDED(hr) );

   pChildNode = pDoc->createElement( _bstr_t(strName) );
   ASSERT( pChildNode != NULL );

   m_pNode->appendChild(pChildNode);

   RELEASE_PTR(pDoc);
  }

  pChild->m_pNode = pChildNode; 
  RELEASE_PTR(pChildNode);
 }
 catch ( _com_error e )
 {
  TRACE( _T("CXmlNode::GetChild发生异常:%s/n"), e.ErrorMessage());
  ASSERT( FALSE );
 }

 return pChild;
}


//-------------------------------------------------------------------------
// Function Name    :NewChild
// Parameter(s)     :CString strName 结点名称
// Return           :CXmlNodePtr
// Memo             :新增一个子结点
//-------------------------------------------------------------------------
CXmlNodePtr CXmlNode::NewChild( CString strName )
{
 ASSERT( m_pNode != NULL );

 CXmlNodePtr pChild( new CXmlNode() );

 try
 {
  MSXML2::IXMLDOMDocumentPtr pDoc = NULL;
  HRESULT hr = m_pNode->get_ownerDocument(&pDoc);
  ASSERT( SUCCEEDED(hr) );

  MSXML2::IXMLDOMNodePtr pChildNode = NULL;
  pChildNode = pDoc->createElement( _bstr_t(strName) );
  ASSERT( pChildNode != NULL );
  RELEASE_PTR(pDoc);

  m_pNode->appendChild(pChildNode);
  pChild->m_pNode = pChildNode;
  RELEASE_PTR(pChildNode);
 }
 catch ( _com_error e )
 {
  TRACE( _T("CXmlNode::NewChild 发生异常:%s/n"), e.ErrorMessage());
  ASSERT( FALSE );
 }
 return pChild; 
}


//-------------------------------------------------------------------------
// Function Name    :AddChild
// Parameter(s)     :CXmlNodePtr & pChildNode
// Return           :void
// Memo             :添加子结点
//-------------------------------------------------------------------------
void CXmlNode::AddChild( CXmlNodePtr & pChildNode)
{
 ASSERT( m_pNode != NULL );

 try
 {
  m_pNode->appendChild( pChildNode->m_pNode );
 }
 catch ( _com_error e )
 {
  TRACE( _T("CXmlNode::AddChild 发生异常:%s/n"), e.ErrorMessage());
  ASSERT( FALSE );
 }
}


//-------------------------------------------------------------------------
// Function Name    :AddChild
// Parameter(s)     :CXmlNode & refChildNode
// Return           :void
// Memo             :添加子结点
//-------------------------------------------------------------------------
void CXmlNode::AddChild( CXmlNode & refChildNode)
{
 ASSERT( m_pNode != NULL );

 try
 {
  m_pNode->appendChild( refChildNode.m_pNode );
 }
 catch ( _com_error e )
 {
  TRACE( _T("CXmlNode::AddChild 发生异常:%s/n"), e.ErrorMessage());
  ASSERT( FALSE );
 }
}


//-------------------------------------------------------------------------
// Function Name    :GetParent
// Parameter(s)     :void
// Return           :CXmlNodePtr
// Memo             :获取父结点
//-------------------------------------------------------------------------
CXmlNodePtr CXmlNode::GetParent(void)
{
 ASSERT( m_pNode != NULL );

 CXmlNodePtr pParent( new CXmlNode() );

 try
 {
  pParent->m_pNode = m_pNode->GetparentNode();
 }
 catch ( _com_error e )
 {
  TRACE( _T("CXmlNode::GetParent 发生异常:%s/n"), e.ErrorMessage());
  ASSERT( FALSE );
 }
 return pParent;
}


//-------------------------------------------------------------------------
// Function Name    :GetName
// Parameter(s)     :void
// Return           :CString
// Memo             :获取当前节点名称
//-------------------------------------------------------------------------
CString CXmlNode::GetName(void)
{
 ASSERT( m_pNode != NULL );

 CString strRet;

 try
 {
  BSTR bstr = NULL;
  HRESULT hr = m_pNode->get_nodeName(&bstr);
  ASSERT( SUCCEEDED(hr) ); 
  strRet = (LPCTSTR)_bstr_t( bstr, true);

  if( bstr != NULL )
  {
   SysFreeString(bstr);
   bstr = NULL;
  }
 }
 catch ( _com_error e )
 {
  TRACE( _T("CXmlNode::GetName 发生异常:%s/n"), e.ErrorMessage());
  ASSERT( FALSE );
 }

 return strRet;
}


//-------------------------------------------------------------------------
// Function Name    :RemoveAttribute
// Parameter(s)     :CString strName IN 属性名称
// Return           :BOOL
// Memo             :删除属性
//-------------------------------------------------------------------------
BOOL CXmlNode::RemoveAttribute( CString strName IN )
{
 ASSERT( m_pNode != NULL );

 HRESULT hr = S_OK;

 try
 {
  MSXML2::IXMLDOMNamedNodeMapPtr pIXMLDOMNamedNodeMap = NULL;
  hr = m_pNode->get_attributes(&pIXMLDOMNamedNodeMap);
  ASSERT( SUCCEEDED(hr) );

  if( SUCCEEDED(hr) )
   pIXMLDOMNamedNodeMap->removeNamedItem( _bstr_t(strName) );
  ASSERT( SUCCEEDED(hr) );

  RELEASE_PTR(pIXMLDOMNamedNodeMap);
 }
 catch ( _com_error e )
 {
  TRACE( _T("CXmlNode::RemoveAttribute 发生异常:%s/n"), e.ErrorMessage());
  ASSERT( FALSE );
  return FALSE;
 }

 
 return SUCCEEDED(hr);
}

//-------------------------------------------------------------------------
// Function Name    :HasChildren
// Parameter(s)     :void
// Return           :BOOL
// Memo             :是否有子结点
//-------------------------------------------------------------------------
BOOL CXmlNode::HasChildren(void)
{
 ASSERT( m_pNode != NULL );

 BOOL bHasChildren = FALSE;
 try
 {
  MSXML2::IXMLDOMNodeListPtr pNodeList = NULL;
  pNodeList = m_pNode->selectNodes( _bstr_t("child::*") );
  ASSERT( pNodeList != NULL );

  bHasChildren = static_cast (pNodeList->length != 0);
  RELEASE_PTR(pNodeList);
 }
 catch ( _com_error e )
 {
  TRACE( _T("CXmlNode::HasChildren 发生异常:%s/n"), e.ErrorMessage());
  ASSERT( FALSE );
 }
 return bHasChildren;
}

//-------------------------------------------------------------------------
// Function Name    :Remove
// Parameter(s)     :
// Return           :
// Memo             :将此结点与父结点分离
//-------------------------------------------------------------------------
CXmlNode & CXmlNode::Remove(void)
{
 ASSERT( m_pNode != NULL );

 try
 {
  HRESULT hr = S_OK;
  MSXML2::IXMLDOMNodePtr pNode = NULL;
  hr = m_pNode->get_parentNode(&pNode);
  ASSERT( SUCCEEDED(hr) );

  pNode->removeChild(m_pNode);
 }
 catch ( _com_error e )
 {
  TRACE( _T("CXmlNode::Remove 发生异常:%s/n"), e.ErrorMessage());
  ASSERT( FALSE );
 }
 return (*this);
}

//-------------------------------------------------------------------------
// Function Name    :RemoveChildren
// Parameter(s)     :
// Return           :BOOL
// Memo             :删除子结点
//-------------------------------------------------------------------------
BOOL CXmlNode::RemoveChildren(void)
{
 ASSERT( m_pNode != NULL );

 try
 {
  MSXML2::IXMLDOMNodeListPtr pNodeList = NULL;
  pNodeList = m_pNode->selectNodes( _bstr_t("child::*") );

  for( int i = 0; i < pNodeList->length; i++)
  {
   m_pNode->removeChild( pNodeList->item[i] );
  }

  RELEASE_PTR(pNodeList);
 }
 catch ( _com_error e )
 {
  TRACE( _T("CXmlNode::Remove 发生异常:%s/n"), e.ErrorMessage());
  ASSERT( FALSE );
  return FALSE;
 }

 return TRUE;
}


//-------------------------------------------------------------------------
// Function Name    :GetChildren
// Parameter(s)     :void
// Return           :CXmlNodesPtr
// Memo             :获取子结点
//-------------------------------------------------------------------------
CXmlNodesPtr CXmlNode::GetChildren()
{
 ASSERT( m_pNode != NULL );

 CXmlNodesPtr pNodes ( new CXmlNodes() );
 try
 {
  MSXML2::IXMLDOMNodeListPtr pNodeList = NULL;
  pNodeList = m_pNode->selectNodes( _bstr_t("child::*") );

  pNodes->m_pNodeList = pNodeList;
  RELEASE_PTR(pNodeList);
 }
 catch ( _com_error e )
 {
  TRACE( _T("CXmlNode::GetChildren 发生异常:%s/n"), e.ErrorMessage());
  ASSERT( FALSE );
 }
 return pNodes;
}


//-------------------------------------------------------------------------
// Function Name    :SelectSingleNode
// Parameter(s)     :LPCTSTR lpszPath 路径
// Return           :CXmlNodePtr
// Memo             :选择单个结点
//-------------------------------------------------------------------------
CXmlNodePtr CXmlNode::SelectSingleNode(LPCTSTR lpszPath)
{
 ASSERT( m_pNode != NULL );

 CXmlNodePtr pNode ( new CXmlNode() );

 try
 {
  MSXML2::IXMLDOMNodePtr pItem = NULL;
  pItem = m_pNode->selectSingleNode( _bstr_t(lpszPath) );

  pNode->m_pNode = pItem;
  RELEASE_PTR(pItem);
 }
 catch ( _com_error e )
 {
  TRACE( _T("CXmlNode::SelectSingleNode 发生异常:%s/n"), e.ErrorMessage());
  ASSERT( FALSE );
 }

 return pNode;
}

//-------------------------------------------------------------------------
// Function Name    :SelectNodes
// Parameter(s)     :LPCTSTR lpszPath 路径
// Return           :CXmlNodesPtr
// Memo             :选择结点集合
//-------------------------------------------------------------------------
CXmlNodesPtr CXmlNode::SelectNodes(LPCTSTR lpszPath)
{
 ASSERT( m_pNode != NULL );

 CXmlNodesPtr pNodes ( new CXmlNodes() );
 try
 {
  MSXML2::IXMLDOMNodeListPtr pNodeList = NULL;
  pNodeList = m_pNode->selectNodes( _bstr_t(lpszPath) );

  pNodes->m_pNodeList = pNodeList;
  RELEASE_PTR(pNodeList);
 }
 catch ( _com_error e )
 {
  TRACE( _T("CXmlNode::SelectNodes 发生异常:%s/n"), e.ErrorMessage());
  ASSERT( FALSE );
 }

 return pNodes;
}


//////////////////////////////////////////////////////////////////////////
// 下列为取值的重载方法

// 取值重载版本
CString CXmlNode::GetValue(LPCTSTR lpszValue /* = NULL */ )
{
 CString strValue;
 _GetValue(strValue);

 if( strValue.IsEmpty() &&
  lpszValue != NULL )
 {
  strValue = lpszValue;
  _SetValue(strValue);
 }

 return strValue;
}

// 取值重载版本
bool CXmlNode::GetValue( bool bDefault )
{
 CString strValue;
 _GetValue(strValue);

 if( strValue.CompareNoCase(_T("1")) == 0 )
 {
  return TRUE;
 }
 else if( strValue.CompareNoCase(_T("0")) == 0 )
 {
  return FALSE;
 }
 else
 {
  strValue = bDefault ? "1" : "0";
  _SetValue(strValue);
  return bDefault;
 } 
}

// 取值重载版本
int CXmlNode::GetValue( int nDefault )
{
 CString strValue;
 _GetValue(strValue);

 if( strValue.IsEmpty() )
 {
  strValue.Format( _T("%d"), nDefault);
  _SetValue(strValue);
 }

 return _ttoi(strValue);
}

// 取值重载版本
float CXmlNode::GetValue( float fDefault )
{
 CString strValue;
 _GetValue(strValue);

 if( strValue.IsEmpty() )
 {
  strValue.Format( _T("%f"), fDefault);
  _SetValue(strValue);
 }

 return static_cast (_tstof(strValue));
}

// 取值重载版本
double CXmlNode::GetValue( double dDefault )
{
 CString strValue;
 _GetValue(strValue);

 if( strValue.IsEmpty() )
 {
  strValue.Format( _T("%.12f"), dDefault);
  _SetValue(strValue);
 }

 return _tstof(strValue);
}


//////////////////////////////////////////////////////////////////////////
// 下列为赋值的重载方法

// 赋值重载版本
BOOL CXmlNode::SetValue( LPCTSTR lpszValue )
{
 CString strValue(lpszValue);
 return _SetValue(strValue);
}

// 赋值重载版本
BOOL CXmlNode::SetValue( bool bValue )
{
 CString strValue;
 strValue = bValue ? _T("1") : _T("0");

 return _SetValue(strValue);
}

// 赋值重载版本
BOOL CXmlNode::SetValue( int nValue )
{
 CString strValue;
 strValue.Format( _T("%d"), nValue);

 return _SetValue(strValue);
}

// 赋值重载版本
BOOL CXmlNode::SetValue( float fValue )
{
 CString strValue;
 strValue.Format( _T("%f"), fValue);

 return _SetValue(strValue);
}

// 赋值重载版本
BOOL CXmlNode::SetValue( double dValue )
{
 CString strValue;
 strValue.Format( _T("%.12f"), dValue);

 return _SetValue(strValue);
}

//////////////////////////////////////////////////////////////////////////
// 下面是获取属性的函数

// 属性取值重载版本
CString CXmlNode::GetAttribute( CString strName, LPCTSTR lpszDefault /* = NULL */)
{
 CString strValue;
 _GetAttribute( strName, strValue);

 if( strValue.IsEmpty() &&
  lpszDefault != NULL )
 {
  strValue = lpszDefault;
  _SetAttribute( strName, strValue);
 }
 return strValue;
}

// 属性取值重载版本
bool CXmlNode::GetAttribute( CString strName, bool bDefault)
{
 CString strValue;
 _GetAttribute( strName, strValue);

 if( strValue.CompareNoCase(_T("1")) == 0 )
 {
  return TRUE;
 }
 else if( strValue.CompareNoCase(_T("0")) == 0 )
 {
  return FALSE;
 }
 else
 {
  strValue = bDefault ? _T("1") : _T("0");
  _SetAttribute( strName, strValue);
  return bDefault;
 } 
}

// 属性取值重载版本
int CXmlNode::GetAttribute( CString strName, int nDefault)
{
 CString strValue;
 _GetAttribute( strName, strValue);

 if( strValue.IsEmpty() )
 {
  strValue.Format( _T("%d"), nDefault);
  _SetAttribute( strName, strValue);
 }

 return _ttoi(strValue);
}

// 属性取值重载版本
float CXmlNode::GetAttribute( CString strName, float fDefault)
{
 CString strValue;
 _GetAttribute( strName, strValue);

 if( strValue.IsEmpty() )
 {
  strValue.Format( _T("%f"), fDefault);
  _SetAttribute( strName, strValue);
 }

 return static_cast (_tstof(strValue));
}

// 属性取值重载版本
double CXmlNode::GetAttribute( CString strName, double dDefault)
{
 CString strValue;
 _GetAttribute( strName, strValue);

 if( strValue.IsEmpty() )
 {
  strValue.Format( _T("%.12f"), dDefault);
  _SetAttribute( strName, strValue);
 }

 return _tstof(strValue);
}


//////////////////////////////////////////////////////////////////////////
// 下面是设置属性的函数

// 属性赋值重载版本
BOOL CXmlNode::SetAttribute( CString strName, LPCTSTR lpszValue)
{
 CString strValue;
 strValue = lpszValue;

 return _SetAttribute( strName, strValue); 
}

// 属性赋值重载版本
BOOL CXmlNode::SetAttribute( CString strName, bool bValue)
{
 CString strValue;
 strValue = bValue ? _T("1") : _T("0");

 return _SetAttribute( strName, strValue); 
}

// 属性赋值重载版本
BOOL CXmlNode::SetAttribute( CString strName, int nValue)
{
 CString strValue;
 strValue.Format( _T("%d"), nValue);

 return _SetAttribute( strName, strValue); 
}

// 属性赋值重载版本
BOOL CXmlNode::SetAttribute( CString strName, float fValue)
{
 CString strValue;
 strValue.Format( _T("%f"), fValue);

 return _SetAttribute( strName, strValue); 
}

// 属性赋值重载版本]
BOOL CXmlNode::SetAttribute( CString strName, double dValue)
{
 CString strValue;
 strValue.Format( _T("%.12f"), dValue);

 return _SetAttribute( strName, strValue); 
}

#pragma once


#include "./XmlNode.h"


class CXmlNodes
{
 friend class CXml;
 friend class CXmlNode;
 friend class CXmlNodes;

public:
 ~CXmlNodes(void);
 CXmlNodes(void);
 CXmlNodes( CXmlNodes & refNodes );

 CXmlNodesPtr operator = (CXmlNodesPtr pNodes);
 CXmlNodes & operator = (CXmlNodes & refNodes);
 CXmlNodePtr operator[] ( LONG lIndex );
 CXmlNodePtr operator[] ( LPCTSTR lpszName );


 LONG GetCount(void);
 void Release(void);

 CXmlNodePtr GetItem( LONG nIndex );
 CXmlNodePtr GetItem( LPCTSTR lpszName );

protected:
 CXmlNodes(MSXML2::IXMLDOMNodeListPtr pNodeList);
 MSXML2::IXMLDOMNodeListPtr m_pNodeList;

};

#include "StdAfx.h"
#include "./xmlnodes.h"


// 下面是构造函数 和 析构函数
CXmlNodes::CXmlNodes(MSXML2::IXMLDOMNodeListPtr pNodeList)
{
 m_pNodeList = pNodeList;
}

CXmlNodes::CXmlNodes( CXmlNodes & refNodes )
{
 m_pNodeList = refNodes.m_pNodeList;
}

CXmlNodes::CXmlNodes(void)
: m_pNodeList(NULL)
{
}

CXmlNodes::~CXmlNodes(void)
{
 Release();
}

//////////////////////////////////////////////////////////////////////////
void CXmlNodes::Release(void)
{
 RELEASE_PTR(m_pNodeList);
}


//-------------------------------------------------------------------------
// Function Name    :operator =
// Parameter(s)     :CXmlNodesPtr pNodes
// Return           :CXmlNodesPtr
// Memo             :重载 = 号
//-------------------------------------------------------------------------
CXmlNodesPtr CXmlNodes::operator = ( CXmlNodesPtr pNodes IN )
{
 RELEASE_PTR(m_pNodeList);

 m_pNodeList = pNodes->m_pNodeList;
 return pNodes;
}


//-------------------------------------------------------------------------
// Function Name    :operator =
// Parameter(s)     :CXmlNodes & refNodes
// Return           :CXmlNodes &
// Memo             :重载 = 号
//-------------------------------------------------------------------------
CXmlNodes & CXmlNodes::operator = (CXmlNodes & refNodes)
{
 RELEASE_PTR(m_pNodeList);

 m_pNodeList = refNodes.m_pNodeList;
 return (*this);
}

//-------------------------------------------------------------------------
// Function Name    :GetCount
// Parameter(s)     :void
// Return           :LONG
// Memo             :获取数量
//-------------------------------------------------------------------------
LONG CXmlNodes::GetCount(void)
{
 ASSERT( m_pNodeList != NULL );

 try
 {
  return m_pNodeList->length;
 }
 catch ( _com_error e )
 {
  TRACE( _T("CXmlNodes::GetCount 发生异常:%s/n"), e.ErrorMessage());
  ASSERT( FALSE );
  return -1;
 }
}

//-------------------------------------------------------------------------
// Function Name    :GetItem
// Parameter(s)     :LONG nIndex 索引
// Return           :CXmlNodePtr
// Memo             :获取集合中的结点
//-------------------------------------------------------------------------
CXmlNodePtr CXmlNodes::GetItem( LONG nIndex )
{
 ASSERT( m_pNodeList != NULL );
 ASSERT( nIndex >= 0 && nIndex < GetCount() );

 CXmlNodePtr pNode ( new CXmlNode(m_pNodeList->item[nIndex]) );

 return pNode;
}


//-------------------------------------------------------------------------
// Function Name    :operator[]
// Parameter(s)     :INT nIndex
// Return           :CXmlNodePtr
// Memo             :作用同 GetItem( LONG nIndex )
//-------------------------------------------------------------------------
CXmlNodePtr CXmlNodes::operator[] ( LONG lIndex )
{
 return GetItem(lIndex);
}


//-------------------------------------------------------------------------
// Function Name    :GetItem
// Parameter(s)     :LPCTSTR lpszName 结点名称
// Return           :CXmlNodePtr
// Memo             :根据名称在结点集中查结点
//-------------------------------------------------------------------------
CXmlNodePtr CXmlNodes::GetItem( LPCTSTR lpszName )
{
 ASSERT( m_pNodeList != NULL );
 ASSERT( lpszName != NULL );
 
 CXmlNodePtr pNode ( new CXmlNode() );

 try
 {
  HRESULT hr = S_OK;
  CString strName;
  BSTR bstr = NULL;
  MSXML2::IXMLDOMNodePtr pItem = NULL; 

  for( int i = 0; i < m_pNodeList->length; i++)
  {
   pItem = m_pNodeList->item[i];

   hr = pItem->get_nodeName(&bstr);  

   strName = (LPCTSTR)_bstr_t( bstr, true);
   if( bstr != NULL )
   {
    SysFreeString(bstr);
    bstr = NULL;
   }

   // 查找第一个相等的
   if( strName.Compare(lpszName) == 0 )
   {
    pNode->m_pNode = pItem;
    RELEASE_PTR(pItem);
    return pNode;
   }

   RELEASE_PTR(pItem);
  }
 }
 catch ( _com_error e )
 {
  TRACE( _T("CXmlNodes::GetItem 发生异常:%s/n"), e.ErrorMessage());
  ASSERT( FALSE );
 }

 return pNode;
}


//-------------------------------------------------------------------------
// Function Name    :operator[]
// Parameter(s)     :LPCTSTR lpszName 结点名称
// Return           :CXmlNodePtr
// Memo             :作用同 GetItem( LPCTSTR lpszName )
//-------------------------------------------------------------------------
CXmlNodePtr CXmlNodes::operator[] ( LPCTSTR lpszName )
{
 return GetItem(lpszName);
}





原创粉丝点击