XML解析器,自己加了点注释。留底

#include <iostream>
#include "1.h"
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;
}

 

 

 

(好看网 www.hk5.cc)

 

 

 

#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
{

 string _Text;

 template<typename T>
 T operator=(T val)  //赋值给_Text
 {
  stringstream ss;
  ss << val;
  _Text = ss.str();
  return val; 
 }

 AttributeType& operator=(AttributeType& val) //赋值给_Text
 {
  _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;} //输出_Text
inline istream& operator>>(istream &in, AttributeType x) { return in >> x._Text; } //输入_Text

//----------------------------------------------
#ifdef _USE_STRING  //如果用了string
typedef string ValueType;

#else
typedef AttributeType ValueType;
#endif

//----------------------------------------------


/// XML类型
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++;//检查参数c是否为空格字符,也就是判断是否为空格('')、定位字符
 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();  }
 //返回string后的值
 ValueType & value(string key)    {  return _Map[key];  }

 
 //返回属性
 string xml()
 {
  string str;
  for(map<string, ValueType>::iterator iter=_Map.begin(); iter!=_Map.end(); iter++)
  {
   str +=  " " +  (string)(iter->first)  +  "=/"  "+ (string)(iter->second) +  "/"";
    ///属性列处理: key1="val_1"  key2="val_2"  key3="&#XXX;"
  }
  return str;
 }
 //解析 属性
 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); //除去头尾空格

   //书本 书名="VC++" 价格="50" 折扣="1"/
   if((L = find(fptr+1, last, ' /" ')) != last)//如果L找到 "
    R = find(L+1, last, ' /" ');            //则R找后面那个
   if(L==last || R==last)                      //如果到达结尾
    break;
    _Map[string(ptr, fptr)] = string(L+1, R);   // (prt,fprt)为属性名  (L+1,R)为属性值
  }
 }
};

 

///节点基类
struct SXmlNode
{
 SXML_Type _Type;    //XML格式
 SXmlNode* _pParent; //自己类指针
 string _Text;       //  数据
 
 SXmlNode(SXmlNode *parent=NULL) : _pParent(parent)    {       }
 virtual ~SXmlNode(){}

 SXmlNode* get_parent()           {   return _pParent;  }
 SXML_Type& type()            { return _Type;   }//获得XML格式

 //赋值
 string& operator=(const char *s)        {  _Text=s;return _Text; }
 string& operator=(string& s)         {  _Text=s;return _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;                    //string
 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);//功能等于 iter+=n;
  return *(*iter); //返回 具体的SXmlNode
 }
 SXmlNodeList::size_type count()//返回总共多少个元素节点
 {
  return size();//多此一举?
 }
 SXmlNodeList::size_type count(string tag_name)//返回 元素名 = 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)//name 节点名。n代表第几个相同的节点
 {
  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)  //XML_ELEMENT, 元素节点
    return *((SXmlElement*)(*iter)); //返回找到的点
   
   throw SXmlExecption("找不到/"" + name +"/"子节点!");
 }
 string& text()            
 {
  for(SXmlNodeList::iterator iter = _pNodes.begin(); iter != _pNodes.end(); iter++)
  {
   if((*iter)->_Type == XML_Text) // XML_Text, //字符块节点
    return (string&)(*((SXmlText*)(*iter)));
  }
  SXmlNode* p = (SXmlNode*)new SXmlText(this);
  _pNodes.insert(_pNodes.begin(),1, p);//插入  insert的参数应该是一个迭代器和一个要插入的值  、

  return (string&)(*p);
 }
 ///清除所有节点                    
 void clear()
 {
  _Attributes.clear();//清除属性  map 类型
  for(SXmlNodeList::iterator iter=_pNodes.begin(); iter!=_pNodes.end(); iter++)
   delete (*iter);
  _pNodes.clear();               //清除元素节点
 }
 virtual string xml()
 {
  string str;
  
  if(type() == XML_ELEMENT)  //XML_ELEMENT, 元素节点
  {
   str = string("<") + _Text;          //
   if(_Attributes.size())              //
    str += _Attributes.xml();       //    _Attributes 属性行
   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);//把_text的ptr fptr中间的部分给 newptr(自动去除空格)
    _pNodes.push_back(newptr);       //再将newptr 赋给 p_Nodes
   }
   
   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); //最上面的 <?xml version="1.0" encoding="gb2312"?>
    newptr->parse(fptr, nptr + 1); //则
    _pNodes.push_back(newptr); //将<?xml?>存进去
    ptr = nptr + 1;            //此时ptr从下一个<开始
    break;
    

   case '!':
    if(!(*(fptr + 2)=='-' && *(fptr + 3)=='-'))//不是寻常的注释 
    //<![CDATA[      ]]>   特殊
    //<DOCTYPE      ]>     DTD
    {                  
     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) //找到了CDATA
      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; //此时ptr从下一个<开始
    break;
    
   default:
    char find_str[] = "/n/r/t/x20/>"; //如果都不是 则    />
   
    SXmlElement *new_elem = new SXmlElement(this);
    
   
    tptr = find_first_of(fptr, nptr, find_str, find_str + 6);//寻找第一个 / 或者 >
    new_elem->_Text = string(fptr+1, tptr-fptr-1);  // <    />里元素赋值给 new_elem 如 书店
    _pNodes.push_back(new_elem);  //将new_elem扔进去
    if(*(nptr-1) == '/')// <elemet .../>
    {
     new_elem->_Attributes.parse(tptr, nptr-1);  //将 element赋值给new_elem
     //  <书本 书名="VC++" 价格="50" 折扣="1"/>
     ptr = nptr + 1; //下一个
    }
    else //</elemet>  </书本>
    {
     new_elem->_Attributes.parse(tptr, nptr);     //将 element赋值给new_elem
     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;                
   //noskipws //不忽略空白
   copy(istream_iterator<char>(rf),istream_iterator<char>(), back_inserter(buf));//把值赋给 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值