• TinyXML用法小结2


    参考:http://www.cnblogs.com/hgwang/p/5833638.html

    TinyXML用法小结

    1.      介绍

    Tinyxml的官方网址:http://www.grinninglizard.com

    官方介绍文档:http://www.grinninglizard.com/tinyxmldocs/tutorial0.html

    在TinyXML中,根据XML的各种元素来定义了一些类:

    TiXmlBase:整个TinyXML模型的基类。

    TiXmlAttribute:对应于XML中的元素的属性。

    TiXmlNode:对应于DOM结构中的节点。

    TiXmlComment:对应于XML中的注释

    TiXmlDeclaration:对应于XML中的申明部分,即<?versiong="1.0" ?>。

    TiXmlDocument:对应于XML的整个文档。

    TiXmlElement:对应于XML的元素。

    TiXmlText:对应于XML的文字部分

    TiXmlUnknown:对应于XML的未知部分。

    TiXmlHandler:定义了针对XML的一些操作。

    根据下图来说明常用的类对应的文本格式:

    复制代码
    <?xml version="1.0" ?> //TiXmlDeclaration,声明
    <MyApp>    //TiXmlElement,元素
        <!-- Settings for MyApp -->//TiXmlComment,注释
        <Messages>//TiXmlElement,元素
            <Welcome>Welcome to MyApp</Welcome>
    //<Welcome>是元素TiXmlElement ,“Welcome to MyApp”是TiXmlText,文本
            <Farewell>Thank you for using MyApp</Farewell>//同上
        </Messages>
        <Windows>//TiXmlElement,元素
            <Window name="MainFrame" x="5" y="15" w="400" h="250" />
    // Window是元素TiXmlElement ,name、x、y、h是TiXmlAttribute
        </Windows>
        <Connection ip="192.168.0.1" timeout="123.456000" />
    </MyApp>
    复制代码

          TinyXML是个解析库,主要由DOM模型类(TiXmlBase、TiXmlNode、TiXmlAttribute、TiXmlComment、TiXmlDeclaration、TiXmlElement、TiXmlText、TiXmlUnknown)和操作类(TiXmlHandler)构成。它由两个头文件(.h文件)和四个CPP文件(.cpp文件)构成,用的时候,只要将(tinyxml.h、tinystr.h、tinystr.cpp、tinyxml.cpp、tinyxmlerror.cpp、tinyxmlparser.cpp)导入工程就可以用它的东西了。如果需要,可以将它做成自己的DLL来调用。

    注意,TiXmlBase 是TiXmlNode的基类,TiXmlNode是TiXmlElement、TiXmlComment、TiXmlText、TiXmlDeclaration、TiXmlUnknown、TiXmlDocument的基类。

    2.      TinyXML配置

    在stdafx.h头文件中增加头文件引用#include "tinyxml/tinyxml.h"

    在工程设置中加入lib引用库

    在stdafx.h中加入动态库引用

    #ifdef _DEBUG
    #pragma comment(lib,"TinyXMLD.lib")
    #else
    #pragma comment(lib,"TinyXML.lib")
    #endif

    3.      TinyXML读取和保存文件

    3.1 读取xml文件

    TiXmlDocument lconfigXML;
    if( !lconfigXML.LoadFile( strXmlFile.c_str() ) )
    {
        break;
    }

    3.2 读取xml参数

    复制代码
    TiXmlDocument lActionXML;
    lActionXML.Parse(strRmcpParam.c_str());
    if(lActionXML.Error())
    {
         strErr = "输入参数不是标准的xml格式";
         return false;
     }
    复制代码

    3.3 保存xml参数到文本

    TiXmlDocument tyDoc;
    …
    tyDoc.SaveFile(m_strFilePath);

    3.4 保存xml参数到临时变量

    TiXmlDocument tyDoc;
    …
    TiXmlPrinter printer;
    tyDoc.Accept(&printer);
    std::string devParam = std::string(printer.CStr());

    4.      TinyXML增删改查

    4.1 增

    创建一个如1中的xml文件代码

    复制代码
    void write_app_settings_doc( )  
    {  
        TiXmlDocument doc;  
        TiXmlElement* msg;
         TiXmlDeclaration* decl = new TiXmlDeclaration( "1.0", "", "" );  
        doc.LinkEndChild( decl );   
        TiXmlElement * root = new TiXmlElement( "MyApp" );  
        doc.LinkEndChild( root );  
        TiXmlComment * comment = new TiXmlComment();
        comment->SetValue(" Settings for MyApp " );  
        root->LinkEndChild( comment );   
        TiXmlElement * msgs = new TiXmlElement( "Messages" );  
        root->LinkEndChild( msgs );   
        msg = new TiXmlElement( "Welcome" );  
        msg->LinkEndChild( new TiXmlText( "Welcome to MyApp" ));  
        msgs->LinkEndChild( msg );   
        msg = new TiXmlElement( "Farewell" );  
        msg->LinkEndChild( new TiXmlText( "Thank you for using MyApp" ));  
        msgs->LinkEndChild( msg );   
        TiXmlElement * windows = new TiXmlElement( "Windows" );  
        root->LinkEndChild( windows );  
        TiXmlElement * window;
        window = new TiXmlElement( "Window" );  
        windows->LinkEndChild( window );  
        window->SetAttribute("name", "MainFrame");
        window->SetAttribute("x", 5);
        window->SetAttribute("y", 15);
        window->SetAttribute("w", 400);
        window->SetAttribute("h", 250);
        TiXmlElement * cxn = new TiXmlElement( "Connection" );  
        root->LinkEndChild( cxn );  
        cxn->SetAttribute("ip", "192.168.0.1");
        cxn->SetDoubleAttribute("timeout", 123.456); // floating point attrib
        dump_to_stdout( &doc );
        doc.SaveFile( "appsettings.xml" );  
    } 
    复制代码

    在节点最后插入新节点

    TiXmlNode* LinkEndChild( TiXmlNode* addThis );

    在节点后 前/后 插入新节点

    TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis );
    TiXmlNode* InsertAfterChild(  TiXmlNode* afterThis, const TiXmlNode& addThis );

    4.2 删

    删除某个节点, TiXmlNode是TiXmlElement、TiXmlComment、TiXmlText、TiXmlDeclaration、TiXmlUnknown、TiXmlDocument的基类

    TiXmlNode node;
    node.Clear();

    从A节点上移除子节点B

    TiXmlNode nodeA;
    nodeA. RemoveChild( TiXmlNode* removeThis );

    从元素A上移除名字为B的属性

    TiXmlAttribute attrA;
    attrA. RemoveAttribute( const char * name );

    4.3 改

    查找内容为<mfid val="1234" />,现需要将1234改成其他值

    TiXmlNode* lpnode = NULL;
    lpnode = tixml.RootElement()->IterateChildren("mfid",lpnode);
    TiXmlAttribute* tiattr = lpnode->ToElement()->FirstAttribute();
    //找到mfid节点,获取第一个属性值。注意,如果有多个属性值,需要判断哪个属性值是需要的
    tiattr->SetValue(mfid.c_str());

    替换一个节点

    TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ); 

    4.4 查

    获取link节点

    复制代码
    const TiXmlNode* lpItemNode = NULL;//初始化
    lpItemNode = lconfigXML.RootElement()->IterateChildren("link", lpItemNode);
    if (lpItemNode == NULL)
    {
        //Can not find <link>break;
    }
    复制代码

    获取link节点中的type属性值

    std::string strType = lpItemNode->ToElement()->Attribute("type");

    遍历节点

    复制代码
    const TiXmlNode* lpMapNode = NULL; //初始化
    lpMapNode = lconfigXML.RootElement()->IterateChildren("node", lpMapNode);
    if (lpMapNode) 
    {
        rms::CStationMapping litem;
        const TiXmlNode* lpItemNode = NULL ;
        while(lpItemNode = lpMapNode->IterateChildren("item",lpItemNode))
        {
            string str = lpItemNode->ToElement()->Attribute("ABC"); 
        }
    }
    复制代码

    遍历元素属性

    TiXmlAttribute* pAttr = NULL; 
    for (pAttr = pNode->FirstAttribute(); pAttr; pAttr = pAttr->Next())  
    {    
      …
    }

    节点的下一个兄弟节点

    const TiXmlNode* NextSibling() const;

    元素的下一个元素

    const TiXmlElement* NextSiblingElement() const;

    属性的下一个属性

    const TiXmlAttribute* Next() const;

    返回值为NULL表示不存在

    5.  TinyXml常用操作封装

       使用TinyXml的时候,经常会遇到两个问题:

      1:TinyXml不检查输入参数,如果参数输入不当,会偶发异常。且该异常不易捕捉。

      2:处理较大规模xml的时候,类似IterateChildren等的语句会出现很多行,重复代码量很大。 为解决以上两个问题,我对TinyXml进行简单封装。对于问题1,定义了几种处理状态,当参数不当或其他问题发生时,会返回对应的错误代码。用GetStatus可解析出该异常。 

    复制代码
      1 //tinyxml 宏
      2 //N:Node,C:Child node,Cn:Child node's name,An:Attribute name,V:Value(string类型)
      3 //D:tixmldocument,P:tixmlprinter,p:param,Pre:previous
      4 #ifndef TNXML_COMMON
      5 #define TNXML_COMMON
      6 
      7 #define TNXML_XML_PARAM            -2
      8 #define TNXML_XML_FILE            -1
      9 
     10 #define TNXML_OK                0
     11 #define TNXML_NOT_FIND_NODE        1
     12 #define TNXML_NOT_FIND_ATTR        2
     13 #define TNXML_PARAM_NODE_NULL    3
     14 #define TNXML_PARAM_STR_NULL    4
     15 #define TNXML_PARAM_NOT_XML        5
     16 #define TNXML_OTHER_ERROR        9
     17 
     18 class CTNXML
     19 {
     20 public:
     21     //查找节点N下子节点Cn(Pre节点后),用output返回
     22     static int CN(TiXmlNode* N,std::string Cn,TiXmlNode* Pre,TiXmlNode*& output)
     23     {
     24         if (N == NULL)
     25         {
     26             return TNXML_PARAM_NODE_NULL;
     27         }
     28         if (Cn.empty())
     29         {
     30             return TNXML_PARAM_STR_NULL;
     31         }
     32         TiXmlNode* node =  N->IterateChildren(Cn.c_str(),Pre);
     33         if (node)
     34         {
     35             output = node;
     36             return TNXML_OK;
     37         }
     38         else
     39         {
     40 
     41             return TNXML_NOT_FIND_NODE;
     42         }
     43     }
     44 
     45     //查找节点N下属性An的值,用output返回
     46     static int ELE_ATTR_VAL(TiXmlNode* N,std::string An,std::string& output)
     47     {
     48         if (N == NULL)
     49         {
     50             return TNXML_PARAM_NODE_NULL;
     51         }
     52         else if (An.empty())
     53         {
     54             return TNXML_PARAM_STR_NULL;
     55         }
     56         if (N->ToElement()->Attribute(An.c_str()) == NULL)
     57         {
     58             return TNXML_NOT_FIND_ATTR;
     59         }
     60         else
     61         {
     62             output = N->ToElement()->Attribute(An.c_str());
     63             return TNXML_OK;
     64         }
     65     }
     66 
     67     //查找节点N下子节点Cn(Pre节点后),用output返回Cn下属性An的值
     68     static int ITER_ELE_ATTR_VAL(TiXmlNode* N,std::string Cn,TiXmlNode* Pre,std::string An,std::string& output)
     69     {
     70         TiXmlNode* node = NULL;
     71         int res = CN(N,Cn,Pre,node);
     72         if ( res == TNXML_OK)
     73         {
     74             std::string str;
     75             res = ELE_ATTR_VAL(node,An,str);
     76             if (res == TNXML_OK)
     77             {
     78                 output = str;
     79                 return TNXML_OK;
     80             }
     81             else
     82             {
     83                 return res;
     84             }
     85         }
     86         else
     87         {
     88             return res;
     89         }
     90     }
     91 
     92     //设置节点N下属性An的值为V
     93     static int ELE_SET_ATTR(TiXmlNode* N,std::string An,std::string V)
     94     {
     95         if (N == NULL)
     96         {
     97             return TNXML_PARAM_NODE_NULL;
     98         }
     99         else if (An.empty())
    100         {
    101             return TNXML_PARAM_STR_NULL;
    102         }
    103         else
    104         {
    105             N->ToElement()->SetAttribute(An.c_str(),V.c_str());
    106             return TNXML_OK;
    107         }
    108     }
    109 
    110     //设置节点N下子节点Cn(Pre后)属性An的值为V
    111     static int ITER_ELE_SET_ATTR_VAL(TiXmlNode* N,std::string Cn,TiXmlNode* Pre,std::string An,std::string V)
    112     {
    113         TiXmlNode* node = NULL;
    114         int res = CN(N,Cn,Pre,node);
    115         if ( res == TNXML_OK)
    116         {
    117             res = ELE_SET_ATTR(node,An,V);
    118             return res;
    119         }
    120         else
    121         {
    122             return res;
    123         }
    124     }
    125 
    126     //读取xml参数(字符串),返回根节点
    127     static int PARAM_TO_ROOTELE(std::string& str,TiXmlElement* output)
    128     {
    129         if (str.empty())
    130         {
    131             return TNXML_PARAM_STR_NULL;
    132         }
    133         TiXmlDocument* D = new TiXmlDocument;
    134         if (D->Parse(str.c_str()))
    135         {
    136             output =  D->RootElement();
    137             if (output)
    138             {
    139                 return TNXML_OK;
    140             }
    141             else
    142             {
    143                 return TNXML_PARAM_NOT_XML;
    144             }
    145         }
    146         else
    147         {
    148             return TNXML_PARAM_NOT_XML;
    149         }
    150     }
    151 
    152     //读取xml参数(文件地址),返回根节点
    153     static int DOC_TO_ROOTELE(std::string& str,TiXmlElement* output)
    154     {
    155         if (str.empty())
    156         {
    157             return TNXML_PARAM_STR_NULL;
    158         }
    159         TiXmlDocument* D = new TiXmlDocument;
    160         if (D->LoadFile(str.c_str()))
    161         {
    162             output =  D->RootElement();
    163             if (output)
    164             {
    165                 return TNXML_OK;
    166             }
    167             else
    168             {
    169                 return TNXML_PARAM_NOT_XML;
    170             }
    171         }
    172         else
    173         {
    174             return TNXML_PARAM_NOT_XML;
    175         }
    176     }
    177 
    178     //N尾部插入名为Cn的新节点,属性名值An,值V
    179     static int LinkNewNodeWithAttr(TiXmlNode* N,std::string Cn,std::string An,std::string V,TiXmlElement*& C)
    180     {
    181         if (N == NULL)
    182         {
    183             return TNXML_PARAM_NODE_NULL;
    184         }
    185         if (Cn.empty() || An.empty())
    186         {
    187             return TNXML_PARAM_STR_NULL;
    188         }
    189         TiXmlElement* ele = new TiXmlElement(Cn);
    190         ele->SetAttribute(An,V);
    191         N->LinkEndChild(ele);
    192 
    193         C = ele;
    194         return TNXML_OK;
    195     }
    196 
    197     //保存TiXmlDocument文档为字符串
    198     static  int Doc_To_String(TiXmlDocument& D,std::string& output)
    199     {
    200         TiXmlPrinter t_printer;    
    201         if (D.Accept(&t_printer))
    202         {
    203             output = std::string(t_printer.CStr());
    204             return TNXML_OK;
    205         }
    206         else
    207         {
    208             return TNXML_OTHER_ERROR;
    209         }
    210     };
    211 
    212     //保存TiXmlElement文档为字符串
    213     static  int Ele_To_String(TiXmlElement* N,std::string& output)
    214     {
    215         if (N==NULL)
    216         {
    217             return TNXML_PARAM_NODE_NULL;
    218         }
    219         TiXmlNode* ele = N->Clone();
    220         if (ele)
    221         {
    222             TiXmlDocument doc;
    223             doc.LinkEndChild(ele);
    224             return Doc_To_String(doc,output);
    225         }
    226         else
    227         {
    228             return TNXML_OTHER_ERROR;
    229         }
    230     };
    231 
    232     //保存ele至本地文件
    233     static  int Ele_To_File(TiXmlElement* N,std::string filepath)
    234     {
    235         if (N==NULL)
    236         {
    237             return TNXML_PARAM_NODE_NULL;
    238         }
    239         TiXmlNode* ele = N->Clone();
    240         TiXmlDocument doc;
    241         doc.LinkEndChild(ele);
    242         doc.SaveFile(filepath.c_str());
    243         return TNXML_OK;
    244     };
    245 
    246     
    247     //将字符串转成小写
    248     static void Xml_To_Lower(std::string& param)
    249     {
    250         std::transform(param.begin(), param.end(), param.begin(), std::tolower);
    251     }
    252 
    253     //解析以上函数反馈信息
    254     static std::string GetStatus(int index)
    255     {
    256         switch (index)
    257         {
    258         case TNXML_OK:
    259             {
    260                 return std::string("OK");
    261             }
    262         case TNXML_NOT_FIND_NODE:
    263             {
    264                 return std::string("Cannot find node");
    265             }
    266             break;
    267         case TNXML_NOT_FIND_ATTR:
    268             {
    269                 return std::string("Cannot find attribute");
    270             }
    271             break;
    272         case TNXML_PARAM_NODE_NULL:
    273             {
    274                 return std::string("Input param node is NULL");
    275             }
    276             break;
    277         case TNXML_PARAM_STR_NULL:
    278             {
    279                 return std::string("Input param string is NULL");
    280             }
    281             break;
    282         case TNXML_PARAM_NOT_XML:
    283             {
    284                 return std::string("Input param string is not XML");
    285             }
    286             break;
    287         case TNXML_OTHER_ERROR:
    288             {
    289                 return std::string("Other errors");
    290             }
    291             break;
    292         default:
    293             {
    294                 return std::string("Unknown");
    295             }
    296             break;
    297         }
    298     }
    299 };
    300 
    301 #endif
    复制代码

          以上是我目前经常用到的处理语句,以后会逐步扩展其他操作语句。

    6.      一个完整例子

    复制代码
    void AppSettings::load(const char* pFilename)
    {
        TiXmlDocument doc(pFilename);
        if (!doc.LoadFile()) return;
    
        TiXmlHandle hDoc(&doc);
        TiXmlElement* pElem;
        TiXmlHandle hRoot(0);
    
        // block: name
        {
            pElem=hDoc.FirstChildElement().Element();
            // should always have a valid root but handle gracefully if it does
            if (!pElem) return;
            m_name=pElem->Value();
    
            // save this for later
            hRoot=TiXmlHandle(pElem);
        }
    
        // block: string table
        {
            m_messages.clear(); // trash existing table
    
            pElem=hRoot.FirstChild( "Messages" ).FirstChild().Element();
            for( pElem; pElem; pElem=pElem->NextSiblingElement())
            {
                const char *pKey=pElem->Value();
                const char *pText=pElem->GetText();
                if (pKey && pText) 
                {
                    m_messages[pKey]=pText;
                }
            }
        }
    
        // block: windows
        {
            m_windows.clear(); // trash existing list
    
            TiXmlElement* pWindowNode=hRoot.FirstChild( "Windows" ).FirstChild().Element();
            for( pWindowNode; pWindowNode; pWindowNode=pWindowNode->NextSiblingElement())
            {
                WindowSettings w;
                const char *pName=pWindowNode->Attribute("name");
                if (pName) w.name=pName;
                
                pWindowNode->QueryIntAttribute("x", &w.x); // If this fails, original value is left as-is
                pWindowNode->QueryIntAttribute("y", &w.y);
                pWindowNode->QueryIntAttribute("w", &w.w);
                pWindowNode->QueryIntAttribute("hh", &w.h);
    
                m_windows.push_back(w);
            }
        }
    
        // block: connection
        {
            pElem=hRoot.FirstChild("Connection").Element();
            if (pElem)
            {
                m_connection.ip=pElem->Attribute("ip");
                pElem->QueryDoubleAttribute("timeout",&m_connection.timeout);
            }
        }
    }

    复制代码
  • 相关阅读:
    js处理json数据,java处理json数据
    sqlmap中##和$$的区别
    tar.gz和bin,以及rpm,deb等linux后缀的文件的区别
    ibatis内置类型
    1099端口被占问题
    动态代理与静态代理的区别
    条款36:绝不重新定义继承而来的non-virtual函数(Never redefine an inherited non-virtual function)
    条款35:考虑virtual函数以外的其他选择(Consider alternative to virtual functions)
    条款34:区分接口继承和实现继承(Different between inheritance of interface and inheritance of implemenation)
    工作好习惯(18之后)
  • 原文地址:https://www.cnblogs.com/lyggqm/p/7240948.html
Copyright © 2020-2023  润新知