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 需要之后,它就会给您一条成长途径。
附:C/C++ 开发人员的解析器
库 | 供应商 | 事件 | 文档 | 特点 | 许可证 |
expat | James Clark/expat 小组 | 本机与 SAX | - | 带有本机 API 和 SAX 封装器的、非常快速的推模型解析器。 | LGPL( 免费 ) |
libxml | Gnome | SAX | DOM | 非常强壮;SAX 与 DOM 封装器;执行 DTD 验证 | LGPL(免费 ) |
MSXML | Microsoft | SAX | DOM | Win32 的 Microsoft XML 库 | EULA(免费 ) |
Xerces | Apache Software Foundation | SAX | DOM | 执行 SAX 及 DOM 级别 1 和 2;DTD 验证;增加的 XML 模式 | Apache(免费 ) |
XTL | Vivid Creations | SAX | DOM | 带 SAX 和 DOM 的基于 STL 的 XML 工具箱 | 商业 |
RXP | 爱丁堡大学 | - | 本机 | 验证以 C 编写的了解名称空间的 XML 解析器 | GPL(免费 ) |
XML 4C | IBM alphaWorks | SAX | DOM | IBM 发起的 Xerces 的变体 | Apache(免费 ) |
Oracle XDK 8i | Oracle | SAX | DOM | Oracle 主办的用于 C++ 的 XML 工具箱 | 非商业 |
Pull Parser | Extreme! Lab | - | 本机 | 印地安那大学发起的用于 C++ 的轻量型 XML 工具箱 | 非商业 |
XML Booster | PhiDaNi 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 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);
//合理性验证方法[_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