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);
        }
    }
}

复制代码
原文地址:https://www.cnblogs.com/lyggqm/p/7240948.html