C/C++读写xml文件

2 篇文章 0 订阅

MSXML2::IXMLDOMDocumentPtr pDoc;
MSXML2::IXMLDOMElementPtr  xmlRoot ;
 // 创建DOMDocument对象
 HRESULT hr  =  pDoc.CreateInstance(__uuidof(MSXML2::DOMDocument40));
 if ( ! SUCCEEDED(hr))
  { 
 MessageBox( " 无法创建DOMDocument对象,请检查是否安装了MS XML Parser 运行库! " );
  return  ;

 // 根节点的名称为Book
 // 创建元素并添加到文档中

 xmlRoot = pDoc -> createElement((_bstr_t) " Book " );
 // 设置属性
 xmlRoot -> setAttribute( " id " ,( const   char   * )m_strId);
pDoc -> appendChild(xmlRoot);
MSXML2::IXMLDOMElementPtr pNode;
 // 添加“author”元素
 pNode = pDoc -> createElement((_bstr_t) " Author " );
pNode -> Puttext((_bstr_t)( const   char   * )m_strAuthor);
xmlRoot -> appendChild(pNode);
 // 添加“Title”元素
 pNode = pDoc -> createElement( " Title " );
pNode -> Puttext(( const   char   * )m_strTitle);
xmlRoot -> appendChild(pNode);
 // 保存到文件
 // 如果不存在就建立,存在就覆盖
 
 pDoc -> save( " d://he.xml " );

------------------------------------------------------------------------------------------------------------------------------------------------

MSXML2::IXMLDOMDocumentPtr pDoc;
HRESULT hr;
hr = pDoc.CreateInstance(__uuidof(MSXML2::DOMDocument40));
 if (FAILED(hr))

  MessageBox( " 无法创建DOMDocument对象,请检查是否安装了MS XML Parser 运行库! " );
  return  ;

 // 加载文件  
 pDoc -> load( " d://he.xml " );
MSXML2::IXMLDOMNodePtr  pNode;
 // 在树中查找名为Book的节点," // "表示在任意一层查找  
 pNode = pDoc -> selectSingleNode( " //Book " );
MSXML2::DOMNodeType nodeType;
 // 得到节点类型  
 pNode -> get_nodeType( & nodeType);
 // 节点名称  
 CString strName;
strName = ( char   * )pNode -> GetnodeName();
 // 节点属性,放在链表中  
 MSXML2::IXMLDOMNamedNodeMapPtr pAttrMap = NULL;
MSXML2::IXMLDOMNodePtr   pAttrItem;
_variant_t variantvalue;
pNode -> get_attributes( & pAttrMap);
 long  count;
count = pAttrMap -> get_length( & count);
pAttrMap -> get_item( 0 , & pAttrItem);
 // 取得节点的值
 pAttrItem -> get_nodeTypedValue( & variantvalue);
m_strId = ( char   * )(_bstr_t)variantvalue;

// 添加整个文档的根节点
 void AddRootNode( CString strRootNode , CString strText = "")
 {
  m_pElement = m_pDoc->createElement( (LPCTSTR)strRootNode );
  m_pElement ->put_text( _bstr_t( (LPCTSTR)strText) );

  m_pDoc->appendChild( m_pElement );
 }

 

三种最流行的开放源码 XML 库 是 expat、libxml 和 Xerces。这三者都是跨平台的,每一种都充当 XSLT 实现的基础,一旦满足了基本 XML 需要之后,它就会给您一条成长途径。

  • expat 是 James Clark 创始的开放源码面向事件的 XML 解析 。他已经将该项目转让给了 SourceForge 中的一个小组。有一个 SAX 封装器可供使用。在许多项目中都可以找到 expat 解析器,如开放源码浏览器 Mozilla、XSLT 处理器 Transformiix 和 RDF 工具 repat。
  • libxml 为类似于 SAX 和 DOM 的操作提供了双重方式 API。它支持对 DTD 的验证,并且在 Gnome 的 XSLT 处理器libxslt 中使用。libxml 经过重写,已作为 libxml(2) 发布,也许还称为 libxml2 。这个 的用户应该确保他们拥有了当前版本。
  • Xerces 是非常坚固的、拥有大量文档的 ,它充当 IBM alphaWorksXML 4C 的基础。Xerces 还用于 Apache XSLT 处理器 Xalan 中。Xerces 支持 DOM、SAX,以及对 DTD 的验证。最新版本读取并解释了部分“W3CXML 模式推荐”(打算到 2001 年底实现完整的XML 模式支持)。


附:C/C++ 开发人员的解析器

供应商 事件 文档 特点 许可证
expatJames Clark/expat 小组本机与 SAX-带有本机 API 和 SAX 封装器的、非常快速的推模型解析器。LGPL( 免费
libxml GnomeSAXDOM非常强壮;SAX 与 DOM 封装器;执行 DTD 验证LGPL(免费
MSXMLMicrosoftSAXDOMWin32 的 Microsoft XML 库 EULA(免费
XercesApache Software FoundationSAXDOM执行 SAX 及 DOM 级别 1 和 2;DTD 验证;增加的 XML 模式Apache(免费
XTLVivid CreationsSAXDOM带 SAX 和 DOM 的基于 STL 的 XML 工具箱商业
RXP爱丁堡大学-本机验证以 C 编写的了解名称空间的 XML 解析器GPL(免费
XML 4CIBM alphaWorksSAXDOMIBM 发起的 Xerces 的变体Apache(免费
Oracle XDK 8iOracleSAXDOMOracle 主办的用于 C++ 的 XML 工具箱非商业
Pull ParserExtreme! Lab-本机印地安那大学发起的用于 C++ 的轻量型 XML 工具箱非商业
XML BoosterPhiDaNi Software-本机解析器发生器,生成 C 源码解析器商业


-------------------------------------------------------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   //默认面板个数
#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);
 
 
 
 //合理性验证方法[_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.pus

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值