Boost读取XML配置文件




  前两天因工作需要写了个xml配置脚本解析的功能类,虽说有N种方式可以实现,但考虑到

Boost库在此方面的易操作性(虽支持不够健全,如Unicode支持等)所以封装了一下,具体如下:

//CProcessXmlConfigFile.h(此类由Dll导出)

#i nclude "stdafx.h"
#pragma once

#i nclude <boost/noncopyable.hpp>
#i nclude <boost/property_tree/ptree.hpp>
#i nclude <boost/property_tree/xml_parser.hpp>
#i nclude <boost/tuple/tuple.hpp>
#i nclude <boost/shared_ptr.hpp>
#i nclude <list>
#i nclude "header.h"

#define MAX_PANLIST_NUM 9   //默认面板个数
#define MAX_FNAME_LEN 256  //文件名长度宏
using namespace boost::property_tree;
typedef ptree xmlParser;
typedef vector<string> panNames_t;
typedef boost::shared_ptr<string> sh_pstr;
typedef boost::tuples::tuple<sh_pstr, size_t, sh_pstr> node_t;
typedef std::list<node_t > ptree_nodes_t;
//////////////////////////////////////////////////////////////////////////
class AFX_EXT_CLASS CProcessXmlConfigFile :  
 private boost::noncopyable
{
public:
 virtual ~CProcessXmlConfigFile(void);
 //获取类唯一实例的静态方法
 static CProcessXmlConfigFile& instance(const string& xmlfile);
 //|=======================================|
 //| 以下为设置xml文件的各方法                                 |
 //|=======================================|
 /*获取面板对象名称列表*/
 void getPanListInfo(void);
 /*获取指定面板下的树列表*/
 void getTreeInfoOfPan(PanIndex _index);

 /*返回面板对象列表*/
 inline panNames_t getPanList(void) const { return m_panobj; }
 /*返回当前面板下的树列表对象*/
 inline ptree_nodes_t getPtreeNodeList(void) const { return m_ptreeobj; }
private:
 CProcessXmlConfigFile(const string& xmlfile);

 CProcessXmlConfigFile(const CProcessXmlConfigFile&);
 CProcessXmlConfigFile& operator=(const CProcessXmlConfigFile&);
 /************************************************************************/
 /* 以下为内部功能方法                                                       */
 /************************************************************************/
 //合理性验证方法[_index:面板索引]
 bool ICanWork(PanIndex _index);
 //加载文件[xml文件名<含路径>]
 bool loadfile(const string& xmlfile);
 //递归遍历节点目录树函数[nodepath:节点路径<分割符为'/'>]
 void recursive_print(const string& nodepath);
private:
 xmlParser m_parser;     //xml文件解析对象
 panNames_t m_panobj;//存储面板对象列表
 //存储当前面板下的树节点对象列表
 ptree_nodes_t m_ptreeobj; 
};

//CProcessXmlConfigFile.cpp

#i nclude "StdAfx.h"
#i nclude "ProcessXmlConfigFile.h"
#i nclude <iostream>
// #i nclude <boost/foreach.hpp>
#i nclude <boost/format.hpp>
#i nclude <boost/typeof/typeof.hpp>
#i nclude <boost/make_shared.hpp>
// #i nclude <boost/ref.hpp>
// #i nclude <boost/program_options/detail/convert.hpp>
// #i nclude <boost/program_options/detail/utf8_codecvt_facet.hpp>
// #i nclude <windows.h>
// #i nclude <stdlib.h>

using namespace std;
using namespace boost;
//参数默认值..
const int iDefaultInt = 0;
const string strNullString = "";
const char chflag = '/';
const string strPan = "doc/pans/pan";
const string strflag = "<xmlattr>";
const wstring win32_dir_splitchar = L"\\";
//////////////////////////////////////////////////////////////////////////
CProcessXmlConfig:CProcessXmlConfigFile(const string& xmlfile)           
{
 loadfile(xmlfile);
 m_panobj.clear();
 m_panobj.reserve(MAX_PANLIST_NUM);
}

CProcessXmlConfig:~CProcessXmlConfigFile(void)
{
}

CProcessXmlConfigFile& CProcessXmlConfig:instance(const string& xmlfile)
{
 static CProcessXmlConfigFile _instance(xmlfile);
 return _instance;
}

void CProcessXmlConfig:getPanListInfo( void )
{
 //开始获取.
 //首先获取总面板节点个数
  assert(m_parser.get_optional<int>("doc.pans.<xmlattr>.glcount"));
 //循环获取各节点名称
 string str = "";
 auto_t(child, m_parser.get_child("doc.pans"));
 for (auto_t(t, child.begin()); t != child.end(); ++t) 
 {
    str = t->first;
  if (str.find("pan") == string::npos)continue;
  m_panobj.push_back(t->second.data());
 }
}

void CProcessXmlConfig:getTreeInfoOfPan( PanIndex _index )
{
 //防御性设计
 if (!ICanWork(_index))return;
 //..
 format fmt("%s-%d");
 fmt % strPan % _index;

 m_ptreeobj.clear();
 recursive_print(fmt.str());
}

bool CProcessXmlConfig:ICanWork( PanIndex _index )
{
 return (_index >= ST_PhysicalCharacteristics && _index <= ST_Report);
}

bool CProcessXmlConfig:loadfile(const string& xmlfile)
{
 //防御性设计
 if (xmlfile.empty())return false;
 //..
 try
 {
  //获取当前应用程序路径..
  wstring strPath(L"");
  {
   TCHAR currPath[MAX_FNAME_LEN+1] = {0};
   GetModuleFileName(NULL, currPath, MAX_FNAME_LEN);
   TCHAR *psz = _tcsrchr(currPath, '\\');
   if (psz)
   {
    *psz = '\0'; //取出程序所在的目录  
     lstrcat(currPath, win32_dir_splitchar.c_str());
    strPath = currPath;
   }  
  }
  //加载配置文件.
  string xmlfilePath = WideToASCII(strPath.c_str()) + xmlfile;
//   std::locale oldLocale;
//   std::locale utf8Locale(oldLocale,
//   new boost::program_options::detail::utf8_codecvt_facet());
  read_xml(xmlfilePath, m_parser, xml_parser::no_comments);
 }
 catch(std::exception& e)
 {
   AfxMessageBox(ASCIIToWide(e.what()).c_str());
  return false;
 }

 return true;
}
//递归遍历xml节点目录树函数..
void CProcessXmlConfig:recursive_print( const string& nodepath )
{
 if (nodepath.empty())return;
 static size_t nproc = 0; //记录递归层次[测试留用]
 //..
 string strKey, strKey_, str;
 auto_t(node, m_parser.get_child(ptree::path_type(nodepath, chflag)));
 //获取节点信息
 for (auto_t(pt, node.begin()); pt != node.end(); ++pt)
 {
  strKey = pt->first;
  if (strKey.find(strflag) != string::npos)
   continue;
  str = pt->second.data();
//   for (size_t i = 0; i < nproc; ++i)
//   cout << "\t";
//   cout << strKey << " = " << (str.empty() ? "empty" : str);
  //////////////////////////////////////////////////////////////////////////
  strKey_ = nodepath + "/" + strKey + "/" + strflag;
  auto_t(attr, m_parser.get_child(ptree::path_type(strKey_, chflag)));
  //获取节点属性信息
  for (auto_t(tt, attr.begin()); tt != attr.end(); ++tt)
  {
   string atkey = tt->first;
   size_t atnval = tt->second.get_<int>();
   m_ptreeobj.push_back(make_tuple(sh_pstr(new string(strKey)), atnval, 
   sh_pstr(str.empty() ? new string("empty") : new string(str))));
//  cout << " <" << atkey << ":" << atnval << ">" << endl;
   strKey = nodepath + "/" + pt->first;
   if (atnval > 0) //若子节点数目不止一个则递归遍历
   {
    ++nproc;
    recursive_print(strKey);
   }
  }
 }

  --nproc;
//  cout << "*****************************************\n";
}

//主程序文档类中用到了CViewTree来动态加载节点,具体调用如下:

 instance =
  &CProcessXmlConfig:instance(xmlfile);
 BOOST_ASSERT(instance);
 //获取面板名称列表.
 instance->getPanListInfo();
 szPanName = instance->getPanList();
 if (szPanName.empty())return;

//  BOOST_FOREACH(panNames_t::_type& p, szPanName)
//   AfxMessageBox(CString(p.c_str()));
 for (size_t i = 0; i < szPanName.size(); ++i)
 {
  // 首先生成树
  CViewTree * ptree = new CViewTree;

  if (!ptree)return;
  //......

   FillClassView();

   //......

  }

FillClassView()方法主体如下:

 {

   //防御性设计
   if (m_objtree.empty())return;

   if (m_nindex < 0 || m_nindex >= m_objtree.size())return;

   shared_wnd_ptr pTreeView = m_objtree[m_nindex];

   if (NULL == pTreeView)return;
   //////////////////////////////////////////////////////////////////////////
   //加载配置文件并读取配置数据..
  {
    //获取当前面板树节点集合信息.
    BOOST_ASSERT(instance);
    instance->getTreeInfoOfPan(m_pIndex);
    ptree_nodes_t ptreenodes = instance->getPtreeNodeList();

    if (ptreenodes.empty())return ;
    //动态生成树节点..
    {
     int nsub = 0;
     HTREEITEM item, pitem;
     std::stack<HTREEITEM> S;
     S.push(pitem);
     BOOST_FOREACH(node_t& node, ptreenodes)
     {
      size_t n = node.get<1>();
      string strVal = *node.get<2>();
      if (strVal.empty() || !strVal.compare("empty"))continue;
      if (nsub > 0)
      {
        pitem = S.empty() ? NULL : S.top();
        item  = pTreeView->InsertItem(CString(strVal.c_str()), pitem);
      }
     else
     {
       if (!S.empty()) S.pop();
       pitem = S.empty() ? NULL : S.top();
     
       item = pTreeView->InsertItem(CString(strVal.c_str()), pitem);
     }
     if (0 == n) --nsub;
     else
     {
      nsub = n;
      S.push(item);
      }
     }
   }
 }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 

你可能感兴趣的:(Boost读取XML配置文件)