XML在web的应用是很广泛的,但对于普通c++程序员恐怕用得不多,xml灵活的格式使得一些设置文件描述变得很容易,但是应用他总是困难的,网络上XML解析器庞大的吓人,如果为了解析很简单的XML也要学习一大堆库有点恐怖,反正我是没兴趣,用MSXML版本的不同也很烦人,COM的应用也很啰嗦,所以我写了一个简单的解析器,可以供简单应用,高手就不要看了,这个解析器只支持XML的子集如下:(用于设置文件是足够了,还可以扩展)

<?xml?>
<根元素>
 <元素 属性列/>
 <元素 属性列/>
 <元素 属性列/>文本</元素>
 <元素><子元素>文本</子元素><子元素>文本</子元素></元素>
</根元素>

可以解析成

<SXmlUnknow>
<SXMLElement>
 <SXMLElement 属性列/>
 <SXMLElement 属性列/>
 <SXMLElement 属性列/>SXMLText</元素>
 <SXMLElement><SXMLElement>SXMLText</SXMLElement><SXMLElement>SXMLText</SXMLElement></SXMLElement>
</SXMLElement>

例:

#include  < iostream >
#include  " sxml.h "
/**/ /*<?xml?>
<书店>
    <书本 书名="VC++" 价格="50" 折扣="1"/>
    <书本 书名="VB" 价格="50" 折扣="0.8"/>
    <书本 书名="C#" 价格="50" 折扣="0.7">有源程序光盘</书本>
    <挂历><年份>2006</年份><价格>50</价格></挂历>
</书店>*/

int  main( int  argc,  char   * argv[])
... {
    try
    ...{
        SXmlDOM dom;
        //dom.parse("<?xml?><书店><书本 书名="VC++" 价格="50" 折扣="1"/><书本 书名="VB" 价格="50" 折扣="0.8"/><书本 书名="C#" 价格="50" 折扣="0.7">有源程序光盘</书本><挂历><年份>2006</年份><价格>50</价格></挂历></书店>")
        dom.parseFile("test.xml");
        //查询
        SXmlElement& root = dom.root();
        cout << "有" << root.count("书本") << "本书!"<< endl;
        cout << "VB的价格:" << (int)root.item("书本", 1)["价格"] * (float)root.item("书本", 1)["折扣"] << endl;
        cout << root.at(0).xml();

        SXmlElement& gl = root.item("挂历");
        cout << gl.item("年份").text() << endl;

        //遍历
        SXmlNodeList::iterator iter;
        for(iter = root.begin(); iter!=root.end(); iter++)
            cout << (*iter)->xml();
        
        //赋值
        root.item("书本", 1)["价格"] = 60;
        root.item("书本", 1)["折扣"] = 0.5;
        cout << "VB的价格:" << (int)root.item("书本", 1)["价格"] * (float)root.item("书本", 1)["折扣"] << endl;

        root.item("书本").text() = "有软盘";

        //保存
        dom.saveFile("else.xml");//属性列的顺序将自动排列, 采用了C++  map<>

    }
    catch(exception &e)
    ...{
        cout << e.what() << endl;
    }
    return 0;
}  

解析器源文件:SXML.h

/*
支持XML的子集只支持元素、属性和文本,可用于简单的XML设置文件的解析,采用标准C++不依赖平台及编译器
支持类似文档:
<SXMLElement>
<SXMLElement 属性列/>
<SXMLElement 属性列/>
<SXMLElement 属性列/>SXMLText</元素>
<SXMLElement><SXMLElement>SXMLText</SXMLElement><SXMLElement>SXMLText</SXMLElement></SXMLElement>
</SXMLElement>

提供两个函数用于实体引用,
  SXmlEntityXml 用于 "</">&/'" ======> {"&lt;", "&quot;", "&gt;", "&amp;", "&apos;"}
  SXmlEntityParse 用于 {"&lt;", "&quot;", "&gt;", "&amp;", "&apos;"} =====> "</">&/'"
 
 测试版 llbird wushaojian@21cn.com http://blog.csdn.net/wujian53
*/

#ifndef _SXML_H
#define _SXML_H
#pragma warning(disable: 4530)
#pragma warning(disable: 4786)
#include <map>
#include <iterator>
#include <fstream>
#include <vector>
#include <string>
#include <algorithm>
#include <sstream>
#include <exception>
#include <list>
using namespace std;

struct AttributeType
{
 string _Text;
 template<typename T>
  T operator=(T val){
  stringstream ss;
  ss << val;
  _Text = ss.str();
  return val;
 }
 AttributeType& operator=(AttributeType& val){
  _Text = val._Text;
  return val;
 }
 operator const char*()  { return _Text.c_str();  }
 operator string()  { return _Text;    }
 operator int()   { return atoi(_Text.c_str()); }
 operator long()   { return atol(_Text.c_str()); }
 operator float()  { return atof(_Text.c_str()); }
 operator double()  { return atof(_Text.c_str()); }
};
inline ostream& operator<<(ostream &out, AttributeType x){ return out << x._Text;}
inline istream& operator>>(istream &in, AttributeType x) { return in >> x._Text; }

#ifdef _USE_STRING
typedef string ValueType;
#else
typedef AttributeType ValueType;
#endif

enum SXML_Type{ XML_UNKNOW, XML_ELEMENT, XML_PI, XML_COMMENT, XML_Text, XML_CHAR_DATA, XML_DOC_Type, XML_DOCUMENT};
///异常
class SXmlExecption : public exception
{
 string _Src;
public:
 SXmlExecption(string s) : _Src(s)   {         }
 ~SXmlExecption()throw()      {         }
 const char* what() const throw()   {  return _Src.c_str();  }
};
//除去头尾空格
inline void trim_c_str(const char *&fptr, const char *&lptr)
{
 while(fptr<lptr && isspace(*fptr)) fptr++;
 while(fptr<lptr && isspace(*(lptr-1))) lptr--;
}
//除去头尾空格
inline string& trim_string(string& str)
{
 string::size_type pos;
 for(pos=0; pos<str.length() && isspace(str.at(pos)); pos++);
 str.erase(0, pos);
 for(pos=str.length()-1; pos>=0 && isspace(str.at(pos)); pos--);
 str.erase(pos + 1);
 return str;
}
///将字符转换为实体引用 '<' --> "&lt;"
inline string SXmlEntityXml(string str)
{
 char *entity[] = {"lt", "quot", "gt", "amp", "apos"};
 char *ref = "</">&/'", *f;
 
 for(string::size_type pos=0; pos < str.length(); pos++)
  if((f = strchr(ref, str[pos])))
   str.replace(pos, 1, string("&") + entity[f-ref] + ";");
  return str;
}
///将实体引用转换为字符 "&lt;" --> '<'
inline string SXmlEntityParse(string str)     
{
 char *entity[] = {"lt", "quot", "gt", "amp", "apos"};
 char *ref = "</">&/'", i;
 string r;
 
 for(string::size_type pos = 0, bpos, epos, rlen = 1;
 (bpos=str.find('&', pos))!=string::npos; pos = bpos + rlen)
 {
  epos = str.find(';', bpos);
  if(epos == string::npos)
   throw SXmlExecption("找不到实体引用的右边界';'");
  r.assign(str.begin()+bpos+1, str.begin()+epos);
  
  for(i = 0; i < 5; i++)
   if(r == entity[i])
   {
    str.replace(bpos, epos - bpos + 1, 1, ref[i]);
    break;
   }
   
   if(i == 5)
    throw SXmlExecption("不支持的实体引用!");
 }
 return str;
}
///属性列
struct SXmlAttribute
{
 map<string, ValueType> _Map;
 
 void clear()        {  _Map.clear();   }
 map<string, ValueType>::size_type size() {  return _Map.size();  }
 ValueType& value(string key)    {  return _Map[key];  }
 string xml()
 {
  string str;
  for(map<string, ValueType>::iterator iter=_Map.begin();
  iter!=_Map.end(); iter++)
   str += " " + iter->first  + "=/"" + (string)(iter->second) + "/"";
  return str;
 }
 ///属性列处理: key1="val_1"  key2="val_2"  key3="&#XXX;"
 void parse(const char *first, const char *last)
 {
  trim_c_str(first, last);
  for(const char *ptr=first, *fptr, *L, *R; ptr < last; ptr=R+1)
  {
   if((fptr = find(ptr, last, '='))==last)
    break;
   
   trim_c_str(ptr, fptr);
   if((L = find(fptr+1, last, '/"')) != last)
    R = find(L+1, last, '/"');
   if(L==last || R==last)
    break;
   _Map[string(ptr, fptr)] = string(L+1, R);
  }
 }
};
///节点基类
struct SXmlNode
{
 SXML_Type _Type;
 SXmlNode* _pParent;
 string _Text;
 
 SXmlNode(SXmlNode *parent=NULL) : _pParent(parent)    {       }
 virtual ~SXmlNode(){}
 SXmlNode* get_parent()           {   return _pParent;  }
 SXML_Type& type()            { return _Type;   }
 string& operator=(const char *s)        { return _Text=s, _Text; }
 string& operator=(string& s)         { return _Text=s, _Text; }
 virtual string xml()           { return _Text;   } //>内存数据转换为XML
 operator string&()            { return _Text;   }
 void parse(const char *p)          { parse(p, p+strlen(p)); } //>解析XML
 void parse(const char *f, const char *l)      { _Text.assign(f, l);  }
};
///字符块节点
struct SXmlText : SXmlNode
{
 SXmlText(SXmlNode *parent=NULL) : SXmlNode(parent)    { _Type = XML_Text;  }
};
///其他节点
struct SXmlUnknow : SXmlNode
{
 SXmlUnknow(SXmlNode *parent=NULL) : SXmlNode(parent)   { _Type = XML_UNKNOW;  }
};

#ifdef _USE_LIST
typedef list<SXmlNode*> SXmlNodeList ;
#else
typedef vector<SXmlNode*> SXmlNodeList ;
#endif
///元素节点
struct SXmlElement : public SXmlNode
{
 SXmlNodeList _pNodes;
 SXmlAttribute _Attributes;
 typedef SXmlNodeList::iterator iterator;
 
 SXmlElement(SXmlNode *parent=NULL) : SXmlNode(parent)   { _Type = XML_ELEMENT; }
 virtual ~SXmlElement()             { clear();    }
 string& tag()             { return _Text;   }
 SXmlNodeList::size_type size()         { return _pNodes.size(); }
 SXmlNodeList& nodes()           { return _pNodes;   }
 iterator begin()            { return _pNodes.begin(); }
 iterator end()             { return _pNodes.end(); }
 ValueType& value(string key)         { return  _Attributes.value(key); }
 ValueType& operator[](string key)        { return  _Attributes.value(key); }
 
 SXmlElement& operator =(const SXmlElement& x)
 {
  _Text = x._Text;
  _pNodes = x._pNodes;
  return *this;
 }
 SXmlNode& at(SXmlNodeList::size_type n = 0)
 {
  if(n<0 || n>=size())
   throw SXmlExecption("子节点编号超出范围!");
  
  SXmlNodeList::iterator iter = _pNodes.begin();
  advance(iter, n);
  return *(*iter);
 }
 SXmlNodeList::size_type count()
 {
  return size();
 }
 SXmlNodeList::size_type count(string tag_name)
 {
  SXmlNodeList::iterator iter;
  SXmlNodeList::size_type i;
  
  for(iter = _pNodes.begin(), i = 0; iter != _pNodes.end(); iter++)
   if((*iter)->_Type==XML_ELEMENT&& (*iter)->_Text==tag_name )
    i++;
   return i;
 }
 SXmlElement& newItem(string tag_name)
 {
  string &str = trim_string(tag_name);
  if(!str.length())
   throw SXmlExecption("元素节点标签不应为空字符串!");
  
  SXmlElement* p = new SXmlElement(this);
  p->tag() = str;
  _pNodes.push_back((SXmlNode*)p);
  return (*p);
 }
 SXmlElement& item(string name, SXmlNodeList::size_type n = 0)
 {
  SXmlNodeList::iterator iter;
  SXmlNodeList::size_type i;
  
  for(iter = _pNodes.begin(), i = 0; iter != _pNodes.end(); iter++)
   if((*iter)->_Type==XML_ELEMENT&& (*iter)->_Text==name && i++==n)
    return *((SXmlElement*)(*iter));
   
   throw SXmlExecption("找不到/"" + name +"/"子节点!");
 }
 string& text()            
 {
  for(SXmlNodeList::iterator iter = _pNodes.begin(); iter != _pNodes.end(); iter++)
  {
   if((*iter)->_Type == XML_Text)
    return (string&)(*((SXmlText*)(*iter)));
  }
  SXmlNode* p = (SXmlNode*)new SXmlText(this);
  _pNodes.insert(_pNodes.begin(), 1, p);
  return (string&)(*p);
 }
 ///清除所有节点                    
 void clear()
 {
  _Attributes.clear();
  for(SXmlNodeList::iterator iter=_pNodes.begin(); iter!=_pNodes.end(); iter++)
   delete (*iter);
  _pNodes.clear();
 }
 virtual string xml()
 {
  string str;
  
  if(type() == XML_ELEMENT)
  {
   str = string("<") + _Text;
   if(_Attributes.size())
    str += _Attributes.xml();
   if(_pNodes.size())
   {
    SXmlNodeList::iterator iter;
    for(iter=_pNodes.begin(), str += '>'; iter!=_pNodes.end(); iter++)
     str += (*iter)->xml();
    str += "</" + _Text + ">";
   }
   else
    str += "/>";
  }
  else
   if(_pNodes.size())
   {
    SXmlNodeList::iterator iter;
    for(iter=_pNodes.begin(); iter!=_pNodes.end(); iter++)
     str += (*iter)->xml();
   }
   
   return str;
 }
 void parse(const char *str)
 {
  parse(str, str + strlen(str));
 }
 void parse(const char *first, const char *last)
 {
  const char *ptr = first;//ptr:base pointer 
  const char *fptr, *nptr, *tptr; //fptr:find pointer  nptr:next pointer tptr : temp pointer
  SXmlNode *newptr;//create SXmlNode
  
  while(ptr < last)
  {
   fptr = find(ptr, last, '<');
   if(ptr != fptr)
   {
    newptr = new SXmlText(this);
    newptr->_Text.assign(ptr, fptr);
    _pNodes.push_back(newptr);
   }
   
   if(fptr == last)
    break;
   
   nptr = find(fptr, last, '>');
   if(nptr == last)
    throw SXmlExecption(string(fptr, nptr+1) + "找不到标签的右边界'>'");
   
   switch(*(fptr + 1))
   {
   case '?':
    newptr = new SXmlUnknow(this);
    newptr->parse(fptr, nptr + 1);
    _pNodes.push_back(newptr);
    ptr = nptr + 1;
    break;
    
   case '!':
    if(!(*(fptr + 2)=='-' && *(fptr + 3)=='-'))//不是寻常的注释
    {                  
     const char *cdata_L = "CDATA", *cdata_R = "]]>",*doc_Type_L = "DOCTYPE", *doc_Type_R = "]>";
     if((tptr = search(fptr, nptr, cdata_L, cdata_L+4)) != nptr)
      if((tptr = search(tptr, last, cdata_R, cdata_R+3)) != last)
       nptr = tptr + 2;
      else
       throw SXmlExecption("CDataSection can not find /"]]>/"");
      else
       if((tptr = search(fptr, nptr, doc_Type_L, doc_Type_L+7)) != nptr)
       {
        if((tptr = search(tptr, last, doc_Type_R, doc_Type_R+2)) != last)
         nptr = tptr + 1;
        else
         throw SXmlExecption("DOCTYPE can not find /"]>/"");
       }
    }
    newptr = new SXmlUnknow(this);
    newptr->parse(fptr, nptr + 1);
    _pNodes.push_back(newptr);
    ptr = nptr + 1;
    break;
    
   default:
    char find_str[] = "/n/r/t/x20/>";
    SXmlElement *new_elem = new SXmlElement(this);
    
    _pNodes.push_back(new_elem);
    tptr = find_first_of(fptr, nptr, find_str, find_str + 6);
    new_elem->_Text = string(fptr+1, tptr-fptr-1);
    
    if(*(nptr-1) == '/')//<elemet .../>
    {
     new_elem->_Attributes.parse(tptr, nptr-1);
     ptr = nptr + 1;
    }
    else //</elemet>
    {
     new_elem->_Attributes.parse(tptr, nptr);
     
     string str = string("</") + new_elem->_Text;
     tptr = search(nptr+1, last, str.begin(), str.end());
     if(tptr == last)
      throw SXmlExecption(string(fptr, nptr+1) + "找不到结束标签</element>");
     new_elem->parse(nptr+1, tptr);
     
     nptr = find(tptr, last, '>');
     if(nptr == last)
      throw SXmlExecption(string(fptr, nptr+1) + "找不到标签的右边界'>'");
     ptr = nptr + 1;
    }
   } //switch(*(fptr + 1)) mean: <X
  }//while(ptr < last)
 }
};   
///DOM解析
class SXmlDOM : public SXmlElement
{
public:
 SXmlDOM()
 {
  _Type = XML_DOCUMENT;
 }
 void parseFile(string file_name)
 {
  vector<char> buf;
  ifstream rf(file_name.c_str());
  
  if(rf)
  {
   rf >> noskipws;
   copy(istream_iterator<char>(rf), istream_iterator<char>(), back_inserter(buf));
   clear();
   parse(&*buf.begin(), &*buf.end());
  }
  else
   throw SXmlExecption("无法打开读入文件!");
 }
 void saveFile(string file_name)
 {
  ofstream rf(file_name.c_str());
  if(rf)
   rf << xml();
  else
   throw SXmlExecption("无法打开写入文件!");
 }
 SXmlElement& root()
 {
  for(SXmlNodeList::iterator iter = _pNodes.begin(); iter != _pNodes.end(); iter++)
   if((*iter)->_Type == XML_ELEMENT)
    return *((SXmlElement*)(*iter));
   throw SXmlExecption("找不到根元素!");
 }
};

#endif //_SXML_H

简易XML解析器(C++)相关推荐

  1. Java XML解析器

    使用Apache Xerces解析XML文档 一.技术概述 在用Java解析XML时候,一般都使用现成XML解析器来完成,自己编码解析是一件很棘手的问题,对程序员要求很高,一般也没有专业厂商或者开源组 ...

  2. TinyXML:一个优秀的C++ XML解析器

    读取和设置xml配置文件是最常用的操作,试用了几个C++的XML解析器,个人感觉TinyXML是使用起来最舒服的,因为它的API接口和Java的十分类似,面向对象性很好. TinyXML是一个开源的解 ...

  3. 先弄个XML解析器代码抄一抄 慢慢研究 O(∩_∩)O哈哈~

     出处:http://bbs.csdn.net/topics/390229172 已经自我放逐好几年了.打算去上班得了.在最后的自由日子里,做点有意义的事吧... 先来下载地址    http:/ ...

  4. Phinecos(洞庭散人) 专注于开源技术的研究与应用 TinyXML:一个优秀的C++ XML解析器

    读取和设置xml配置文件是最常用的操作,试用了几个C++的XML解析器,个人感觉TinyXML是使用起来最舒服的,因为它的API接口和Java的十分类似,面向对象性很好. TinyXML是一个开源的解 ...

  5. java xml解析器_Java XML解析器

    java xml解析器 Java XML parser is used to work with xml data. XML is widely used technology to transpor ...

  6. Android XML解析器– XMLPullParser

    Welcome to android xml parser example using XMLPullParser. We will have a sample XML file that we wi ...

  7. Python XML解析器– ElementTree

    Python XML parser provides us an easy way to read the XML file and extract useful data. Today we wil ...

  8. 精短高效的XML解析器,纯C单一程序,应用于银行的国税库行横向联网接口系统中,稳定可靠,运行速度飞快

    来源于:http://www.ej38.com/showinfo/c-xml-169407.html 供各位参考 精短高效的XML解析器,纯C单一程序,应用于银行的国税库行横向联网接口系统中,稳定可靠 ...

  9. XML解析器及相关概念介绍

    前几天看一本介绍JSP的书,上面有对XML解析器的介绍,但看不太懂,在网上搜了一些资料,看后发现原来书中写的不太正确. 通过这篇文章,把本人理解的关于XML解析器和Java下一些XML相关的概念介绍清 ...

最新文章

  1. AIX 查看进程的内存使用情况
  2. linux杀dmol3进程,linux下运行Gaussian09进程被killed - 量子化学 - 小木虫 - 学术 科研 互动社区...
  3. 项目经理原则(转载)
  4. python中的string模块_有没有可能模仿Python中的string模块?
  5. 转再次写给我们这些浮躁的程序员
  6. 如何用css和HTML结合画熊,结合伪元素实现的纯CSS3高级图形绘制
  7. 分布式事务seata只支持MySQL_阿里分布式事务框架Seata原理解析
  8. tcpdump实战详解
  9. Mysql Literal(文字,既常量)
  10. 解密Oracle备份工具-exp/imp
  11. java 鼠标拖拽_JavaScript DOM 鼠标拖拽
  12. 市场经济下,一周休息2.5天难在落实
  13. 数据结构系列之大话数据结构
  14. 高中计算机编程内容,高中信息技术课程标准
  15. java 单击按钮改变背景颜色_java点击按钮换背景颜色?
  16. 块引用—Markdown极简入门教程(6)
  17. Zebras CodeForces - 950C
  18. java 上传图片 生成缩略图_上传图片同时生成缩略图
  19. python求上α分位点_什么是标准正态分布的上α分位点以及怎样求?
  20. C语言----白细胞计数

热门文章

  1. css选择器的优先级,以及用法
  2. git找回被删除的文件
  3. 自制U8简易总账工具
  4. Hessian原理分析
  5. liteide 没有代码提示没有函数跳转 的解决方法
  6. android okgo分页,Android热门网络框架OkGo详解
  7. dapper oracle 参数,c# – 使用dapper查询oracle的集合参数
  8. 浏览器工作原理(四):HTML解析器 HTML Parser
  9. 计算机网络在农业技术方面的应用,浅析计算机网络技术在农业中的应用.pdf
  10. 云存储服务费上涨?OPPO、努比亚筹划自建网盘