类xml数据格式解析

Posted 小小鸟的大梦想

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了类xml数据格式解析相关的知识,希望对你有一定的参考价值。

需要解析一种类xml的数据文件,数据格式如下:

<head> //文件头
    <type>xtype</type>
    <condition>
        key1=value1
        key2=value2
    </condition>
    <mea>
        key3=value3
        key4=value4
    </mea>
    <xxxx>//多个
     ...
     </xxx>
</head>
<data> //数据域,多个
phi rcs ang
1    2    3
2    3    4
</data>
<data>
phi rcs ang
3    4    5
4    5    6
</data>
该数据格式类似xml,我们需要解析的是head中的所有标签,及标签中的键值对(key=value),并将data域中的数据保存成浮点型数组。
采用类似xml的解析方式,递归进行解析

 具体代码如下:

#include <string>
#include <map>
#include <vector>
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;

//首先定义表示数据结的构体
typedef struct stMyDataLabel{
     string Label;
     vector<string> Content;//对于head域,content代表label中的内容(非键值对);对于data域,代表首行数据头(字符串)
     vector<float>  Values;//对应data域中的数据;使用一维数组表示二维数组;二维数组的列数为data域中的Content个数;
     map<string,string> KeyVal;//head域中解析后的键值对
     vector<stMyDataLabel> SubItems;//子标签;标签会嵌套
     stMyDataLabel(){
           Label = "";
           Content.clear();
           Values.clear();
           KeyVal.clear();
           SubItems.clear();
     }
}stMyDataLabel;
class MyDataParse{
public:
     vector<stMyDataLabel> m_Data;//对应文件中的data域
     stMyDataLabel m_Header;//对应文件的head域
     char m_StartLabel;//标签开始字符
     char m_EndLabel;//标签结束字符
public:
     MyDataParse(){
           m_StartLabel = <;
           m_EndLabel = >;
     }
     void Init(){//初始化
           for (vector<stMyDataLabel>::iterator itr = m_Data.begin();itr!=m_Data.end();itr++)
           {
                itr->Content.clear();
                itr->Values.clear();
                itr->KeyVal.clear();
                itr->SubItems.clear();
           }
           m_Header.Content.clear();
           m_Header.Values.clear();
           m_Header.KeyVal.clear();
           m_Header.SubItems.clear();
     }
     //打印解析后的结果
     void Print(ostream& myout){
           myout<<m_Header.Label<<endl;
           for (vector<stMyDataLabel>::iterator itr = m_Header.SubItems.begin();
                itr != m_Header.SubItems.end(); itr++)
           {
                myout<<"\t"<<itr->Label<<"\n";
                for (vector<string>::iterator sitr = itr->Content.begin(); sitr != itr->Content.end(); sitr++)
                {
                     myout<<"\t\t"<<*sitr<<"\t";
                }
                myout<<endl;
                for (auto mitr = itr->KeyVal.begin(); mitr != itr->KeyVal.end(); mitr++)
                {
                     myout<<"\t\t"<<mitr->first<<" = "<<mitr->second<<"\t";
                }
                myout<<endl;
           }
           
           for (vector<stMyDataLabel>::iterator ditr = m_Data.begin();ditr!=m_Data.end();ditr++)
           {
                myout<<ditr->Label<<endl;
                for (vector<string>::iterator sitr = ditr->Content.begin(); sitr != ditr->Content.end(); sitr++)
                {
                     myout<<"\t"<<*sitr<<"\t";
                }
                myout<<endl;
                int dsize = ditr->Content.size();
                int curdidx = 0;
                for(vector<float>::iterator fitr = ditr->Values.begin(); fitr != ditr->Values.end(); fitr++){
                     myout<<"\t"<<*fitr<<"\t";
                     curdidx++;
                     if(curdidx >= dsize){
                           cout<<endl;
                           curdidx=0;
                     }
                }
                myout<<endl;
           }
     }
     bool Parse(char* filename){//读入文件,进行解析
           if(filename == NULL) return false;
           ifstream myin(filename,ios::in);
           bool flag = ParseLabel(myin,m_Header);
           if(!flag) return false;
           while(!myin.eof()){//多个data域
                stMyDataLabel data;
                flag = ParseLabel(myin,data);
                m_Data.push_back(data);
           }
           return flag;
     }
     bool ParseLabel(istream& myin,stMyDataLabel& label){//递归解析标签及内部数据
           string str;
           bool flag = true;
           do{
                myin >> str;
                int sidx=0,eidx=0;
                sidx = str.find(m_StartLabel);
                eidx = str.find(m_EndLabel);
                if(sidx >= 0 && eidx >= 0 && eidx > sidx){//<lable> or </label>
                     if(str.at(sidx+1) != /)//start of <label>
                     {
                           //string substr(int pos = 0,int n = npos) const;//返回pos开始的n个字符组组成的新字符串
                           bool isSub=false;
                           string lableName = str.substr(sidx+1,eidx-sidx-1);
                           if(label.Label != "") isSub = true;//start of subitem‘s <label>
                           //find </label>
                           int sidx2=0,eidx2=0;
                           sidx2 = str.rfind(m_StartLabel);
                           eidx2 = str.rfind(m_EndLabel);                  
                           if(eidx != eidx2 && str.at(sidx2+1) == /)//<label>content</label>, has </label>
                           {
                                string strelab = str.substr(sidx2+2,eidx2-sidx2-2);
                                if(strelab == lableName){
                                     if(isSub){
                                           stMyDataLabel sublabel;
                                           sublabel.Label = lableName;
                                          sublabel.Content.clear();
                                          sublabel.Content.push_back( str.substr(eidx+1,sidx2-eidx-1) );
                                          label.SubItems.push_back(sublabel);
                                     }
                                     else{
                                           label.Label = lableName;
                                          label.Content.clear();
                                          label.Content.push_back( str.substr(eidx+1,sidx2-eidx-1) );
                                     }
                                     continue;
                                }
                                else{
                                     return false;
                                }                               
                           }
                           else{//处理<label>后换行的情况
                                if(isSub){
                                     stMyDataLabel sublabel;
                                     sublabel.Label = lableName;
                                     label.SubItems.push_back(sublabel);
                                     int curIdx = label.SubItems.size()-1;
                                     bool bres = ParseLabel(myin,label.SubItems.at(curIdx));
                                     if(!bres) return false;//subitem format error
                                     else continue;//
                                }
                                else
                                     label.Label = lableName;
                           }
                     }
                     else{// </lable>, 标签结束
                           string elabel = str.substr(sidx+2,eidx-sidx-2);
                           if(elabel == label.Label){//end of this label
                                return true;
                           }
                           else{//format error
                                return false;
                           }
                     }
                }
                else{//content
                     if(label.Label == "data" || label.Label == "DATA"){//data block
                           // 判断字符串是不是数字
                           stringstream sin(str);
                           float val;
                           if(!(sin >> val))//不是数字
                                label.Content.push_back(str);
                           else
                                label.Values.push_back(val);
                     }
                     else//header
                     {
                           int idx = str.find(=);
                           if(idx >= 0){//key=value
                                string strkey = str.substr(0,idx);
                                string strval = str.substr(idx+1);
                                label.KeyVal.insert(make_pair(strkey,strval));
                           }
                           else{
                                label.Content.push_back(str);
                           }
                     }
                }
           }while(flag);        
     }
};

测试(命令行方式)

MyDataParse parse;
parse.Init();
parse.Parse("test.txt");//数据文件
parse.Print(cout);

 

以上是关于类xml数据格式解析的主要内容,如果未能解决你的问题,请参考以下文章

类xml数据格式解析

从 XML 声明片段获取 XML 编码:部分内容解析不支持 XmlDeclaration

java与JSON

iOS开发——XML/JSON数据解析

iOS开发——XML/JSON数据解析

使用Retrofit2解析XML。多个结果列表不起作用