TinyXml心得

来源:互联网 发布:chemdraw mac 编辑:程序博客网 时间:2024/04/28 10:59

读者对象:对TinyXml有一定了解的人。本文是对TinyXml工具的一些知识点的理解。

需要讨论的请联系:QQ 471202412

1  TinyXml中对TiXmlNode进行了分类,是用一个枚举进行描述的。

enum NodeType

{

DOCUMENT,    文档节点

ELEMENT,     元素节点

COMMENT,     还没弄清楚

UNKNOWN,     未知节点

TEXT,        文本节点

DECLARATION, 声明节点

TYPECOUNT    还没弄清楚

};

TiXmlNode * pNode->Type() 函数可以返回节点的类型。

枚举的比较方法:TiXmlText::TEXT == pNode->Type();

 

这几个类型非常重要,尤其是在遍历xml时或者查找一个节点时

我对节点和元素的理解如下:为了说明问题,我使用下面的xml文档来举例说明

<?xml version="1.0" encoding="gb2312"?>

<Persons>       

         <person Id="200" Shengao=34 ClassName="计本0508">

                   <name>vertor</name>

                   <age>20</age>

                   <address encode="utf-8">

                            <country>中国</country>

                            <province>山西</province>

                            <village>王大庄</village>

                   </address>

         </person>

</Persons>

 

2.1 节点:一种对文档结构的描述对象

2.2 元素:对文档某一个数据块的描述

2.3 文本是指没有孩子的节点

   例如<village>大王庄</village>  文本节点是:"大王庄"

   然而判断一个节点是否是文本节点时并不是根据pNode->NoChildren()来判断,而是根据节点的类型来判断

   因为如果一个节点形如:<village></village>它也是没有孩子节点的。

2.4 节点类可以转换成元素对象。

    例如 TiXmlElement * pElement = pNode->ToElement();

    那什么时候需要转换成元素呢?

      当你需要元素的一些属性值是就需要转换了。

2.5 元素跟节点都有关于访问孩子的函数,

元素访问孩子的函数:

  FirstChildElement() 返回当前元素的孩子元素

  NextSiblingElement() 返回当前元素的同级元素

节点访问节点孩子的函数:

  FirstChild()            返回当前节点的孩子节点

  NextSibing()          返回当前节点的同级下一个节点

个人觉得元素访问和节点访问在一般的访问下没有区别,两者都可以访问的孩子

对于一些特殊的情况下才需要区分。比如你要访问属性时,就需要用元素来找到第一个属性值。

2.6 对于遍历一个xml文档时,思路一般是这样的:

  1 载入一个xml

  2 获得根元素(不是根节点)

  3 循环访问每一个根元素的子元素

  4 对每一个子元素进行解析。

         4.1 获取子元素的类型Type

         4.2 switch(Type)

             case TEXT:

                   输出文本节点的值pNode->value()

             case ELEMENT:

                 获取元素的value(这里的value指的是元素的名字,例如:person元素)

                   循环获取元素的每一个属性

                       a 得到元素的第一个属性

                       b do——while循环获取每一个属性和值。

             case COMMENT: 暂时不用管

             case UNKNOWN: 暂时不用管

             case DECLARATION:

                  获取元素的版本,编码方式等等

         4.3 循环遍历子元素的下一级元素(即孙子元素)在这里也可以遍历孙子节点。

             递归调用第四步。

基本思路就是这样,具体代码见后面

2.7 如果定位一个节点

  唯一确定一个节点的方法是根据节点名,属性名,属性值

  1 根据xml的遍历思想找到与给定节点名一样的节点

  2 如果这个节点有属性并且属性名和值与给定的一致,说明找到了。

  3 如果没有一致的,说明解析失败。

  4 如果没有给定属性名和值,则可以默认只查找与节点名一致的节点。

2.8 编码问题

  TinyXml加载一个xml文档时,根据文档的编码方式来加载,在操作过程中需要进行编码转换

  如果encoding=utf-8则在遍历时,需要进行编码转换,具体转换还没找到方法。

 

2.9 指针的 new和释放。

   TinyXml已经帮我们把指针分配的内存进行了管理,在析构函数中进行了处理,我们不需要处理new出来的指针

   如果我们显示的delete时,有可能影响程序运行。

3.0 对于添加一个节点,删除一个节点,更新一个节点时,都需要在最后SaveFile,我就好几次忘了SaveFile,所以调了老半天。

3.1 总的来说,Tinyxml还是不错的,以后继续学习。

部分功能代码

3.2 对于插入一个节点,首先获取要插入节点的父节点,然后进行插入,最需要注意的是在查询父节点的是时候,必须对应同一个文本对象来操作。有可能在两个函数中同时打开了同一个xml文档,虽然名字一样,但是不是同一个xmldocument对象,所以操作会失败。

最后要保存。

/************************************************************************/

/*  创建一个xml文档                                                                    */

/************************************************************************/

void createXml()

{

        

         //创建一个XML的文档对象。

    TiXmlDocument *myDocument = new TiXmlDocument();

         TiXmlDeclaration* decl = new TiXmlDeclaration("1.0","gb2312","yes");

         myDocument->LinkEndChild(decl);

    //创建一个根元素并连接。

    TiXmlElement *RootElement = new TiXmlElement("Persons");

    myDocument->LinkEndChild(RootElement);

   

         for(int i=0; i<10;i++)

         {

                   //创建一个Person元素并连接。

                   TiXmlElement *PersonElement = new TiXmlElement("Person");

                   RootElement->LinkEndChild(PersonElement);

            

                   //设置Person元素的属性。

                   PersonElement->SetAttribute("ID", i);

                   //创建name元素、age元素并连接。

                   TiXmlElement *NameElement = new TiXmlElement("name");

                   TiXmlElement *AgeElement = new TiXmlElement("age");

                   PersonElement->LinkEndChild(NameElement);

                   PersonElement->LinkEndChild(AgeElement);

            

                   //设置name元素和age元素的内容并连接。

                   TiXmlText *NameContent = new TiXmlText("周星星");

                   TiXmlText *AgeContent = new TiXmlText("20");

                   NameElement->LinkEndChild(NameContent);

                   AgeElement->LinkEndChild(AgeContent);

 

         }

        

        

        

        

    //保存到文件

     myDocument->SaveFile("test.xml");

}

 

/************************************************************************/

/*  遍历一个xml文档                                                                   */

/************************************************************************/

void readXml()

{

         //创建一个XML的文档对象。

         TiXmlDocument *myDocument = new TiXmlDocument("Person.xml");

         myDocument->LoadFile();

 

         //获得xml的头,即声明部分

         TiXmlDeclaration* decl = myDocument->FirstChild()->ToDeclaration();

         cout << "xml文件的版本是:" << decl->Version() << endl;

         cout << "xml的编码格式是:" << decl->Encoding() << endl;

 

         //获得根元素

         TiXmlElement *RootElement = myDocument->RootElement();

 

         //输出根元素名称

         cout << RootElement->Value() << endl;

 

         TiXmlNode* pNode  = NULL;

         string msg = "";

         for(pNode=RootElement->FirstChildElement();pNode;pNode=pNode->NextSiblingElement())

         {

                   msg += dumpNode(pNode,0);

         }

         cout << msg << endl;

 

}

 

************************************************************************/

/*描述:遍历一个元素

  时间:2011-5-1

  参数说明:pNode节点,flag节点嵌套层数

/************************************************************************/

string dumpNode(TiXmlNode * pNode,int flag)

{       

         string msg = "";

        

         if(pNode == NULL)

         {

                   return "";

         }

         TiXmlText * pText = NULL;

         TiXmlNode * pChildNode = NULL;

         int t = pNode->Type();

         if(t == TiXmlText::TEXT)  //节点类型是text节点

         {

                   pText = pNode->ToText();

                   string text = pText->Value();

                   if(!text.empty())

                   {

                            msg = msg + "="+ text;

                   }

                  

                  

         }

         else if(t == TiXmlText::ELEMENT) //节点类型是Element

         {

                   msg = msg + "\r\n";

                   int num = flag;

                   while(num >= 1)

                   {

                            msg = msg + "\t";

                            num--;

                   }

                  

                   msg = msg + pNode->Value();

                  

                   //输出属性

                   TiXmlElement * pElement = pNode->ToElement();

                  

                   TiXmlAttribute * pAttr = pElement->FirstAttribute();

                   TiXmlAttribute * pNextAttr =NULL;

                   string tmpAttrMsg = "[";

                   if(pAttr != NULL)

                   {       

                            string tmpAttrVal = "";

                            string tmpAttrName = "";                

                           

                            do

                            {                                                               

                                     tmpAttrVal = pAttr->Value();

                                     tmpAttrName = pAttr->Name();

                                     tmpAttrMsg += tmpAttrName+"=" + tmpAttrVal+",";   //各个属性之间用逗号分隔

                            }while(pAttr = pAttr->Next());

                            tmpAttrMsg = tmpAttrMsg.erase(tmpAttrMsg.find_last_of(","));

                   }

                   tmpAttrMsg += "]";

                   msg += tmpAttrMsg;

                  

         }

         //循环访问它的每一个元素

         for(pChildNode=pNode->FirstChild();pChildNode!=0;pChildNode = pChildNode->NextSibling())

         {

                  

                   msg = msg + dumpNode(pChildNode,flag+1);

 

         }

         return msg;

        

        

}

/************************************************************************/

/* 查询出唯一节点                                                         */

/* 参数说明:

   string nodeName    节点名

   string nodeAttrName 节点的属性

   string nodeAttrValue 节点属性的值

/************************************************************************/

TiXmlNode * SelectSingleNode(string nodeName,string nodeAttrName,string nodeAttrValue)

{

         //加载一个XML的文档对象。

 

         TiXmlDocument *xmlDoc = new TiXmlDocument("Person.xml");

         if(!xmlDoc->LoadFile())    //tinyXml会自动处理文档的BOM

         {

                   return NULL;

         }

         if(xmlDoc == NULL)

         {

                   return NULL;

         }

         //获得根元素

         TiXmlElement *RootElement = xmlDoc->RootElement();

         if(RootElement == NULL)

         {

                   cout << "解析错误,无法获取根元素" << endl;

                   return NULL;

         }

         TiXmlNode * pNode  = NULL;

         TiXmlNode * pSelectNode = NULL;

         string msg = "";

         for(pNode=RootElement->FirstChildElement();pNode;pNode=pNode->NextSiblingElement())

         {

                  

                   pSelectNode = selectChildNode(pNode,nodeName,nodeAttrName,nodeAttrValue);

                   if(pSelectNode)

                   {

                            break;

                   }

         }

        

         if(pSelectNode)

         {

                   cout << "解析成功" << endl;

                   cout << pSelectNode->Value() << endl;

                   return pSelectNode;

         }

         else

         {

                   cout << "解析错误,无法获取节点" << endl;

                   return NULL;

         }

 

}

/************************************************************************/

/*

  根据父节点循环遍历查找子节点

  参数说明

    noteName 节点名

         noteAttrName 属性名

         noteAttrValue 属性值

/************************************************************************/

TiXmlNode * selectChildNode(TiXmlNode * pNode,string nodeName,string nodeAttrName,string nodeAttrValue)

{

         if(pNode == NULL)

         {

                   return NULL;

         }

         TiXmlNode * pSelectedNode = NULL;

         TiXmlNode * pChildNode = NULL;

         int t = pNode->Type();

         switch (t)

         {

         case TiXmlText::DOCUMENT:

         case TiXmlText::DECLARATION:

         case TiXmlText::TEXT:

         case TiXmlText::UNKNOWN:

         case TiXmlText::COMMENT:

                   break;

         case TiXmlText::ELEMENT:

         if(pNode->Value() == nodeName)

         {

                            //cout << pNode->Value() << endl;

                            if(!nodeAttrName.empty() && !nodeAttrValue.empty())

                            {

                                     TiXmlElement * pElement = pNode->ToElement();

 

                                     TiXmlAttribute * pAttr = pElement->FirstAttribute();

                                     TiXmlAttribute * pNextAttr =NULL;

                                     if(pAttr != NULL)

                                     {       

                                               do

                                               {                                                               

                                                        if(pAttr->Name()==nodeAttrName&&pAttr->Value()== nodeAttrValue)

                                                        {

                                                                 //cout << pAttr->Value() << endl;

                                                                 return pNode;

                                                        }

                                               }while(pAttr = pAttr->Next());

                                     }

                            }

                            else

                            {

                                     return pNode;

                            }

                           

                   }

                   else

                   {

                            //循环访问它的每一个元素

                   for(pChildNode=pNode->FirstChild();

pChildNode!=0;

pChildNode = pChildNode->NextSibling())

                            {

                  pSelectedNode = selectChildNode(

pChildNode,

nodeName,

nodeAttrName,

nodeAttrValue);

                            if(pSelectedNode)

                                     {

                                               return pSelectedNode;

                                     }

                            }

                   }

         default:break;

         }

         return NULL;

}

/************************************************************************/

/* 普通插入一个节点,还不完善。                                                               */

/************************************************************************/

bool insert()

{

         //加载一个XML的文档对象。

         TiXmlDocument *myDocument = new TiXmlDocument("Person.xml");

         myDocument->LoadFile();

        

         if(myDocument == NULL)

         {

                   return false;

         }

         //获得xml的头,即声明部分

         TiXmlDeclaration* decl = myDocument->FirstChild()->ToDeclaration();

         if(decl != NULL)

         {

                   cout << "xml文件的版本是:" << decl->Version() << endl;

                   cout << "xml的编码格式是:" << decl->Encoding() << endl;

         }

        

 

         //获得根元素

         TiXmlElement *RootElement = myDocument->RootElement();

   

         if(RootElement != NULL)

         {

 

                   //创建一个Person元素并连接。

                   TiXmlElement *PersonElement = new TiXmlElement("Person");

                   PersonElement->SetAttribute("Id",1);

                   RootElement->LinkEndChild(PersonElement); 

                  

                   TiXmlText *textElement = new TiXmlText("Jam");

                   PersonElement->LinkEndChild(textElement);

                  

                   //增加一个team元素

                   TiXmlElement *TeamElement = new TiXmlElement("team");

                   TeamElement->SetAttribute("TID","001");

                   RootElement->LinkEndChild(TeamElement);

                  

                   //增加team的子节点name

                   TiXmlElement *teamName = new TiXmlElement("name");

                   TiXmlText *nameText = new TiXmlText("workgroup");

                   teamName->LinkEndChild(nameText);

                   TeamElement->LinkEndChild(teamName);

 

                   //增加team的子节点type

                   TiXmlElement *teamType = new TiXmlElement("type");

                   TiXmlText *typeText = new TiXmlText("SI");

                   teamType->LinkEndChild(typeText);

 

                   TeamElement->LinkEndChild(teamType);

 

                   myDocument->SaveFile("Person.xml");

                  

 

                   //输出根元素名称

                   cout << RootElement->Value() << endl;

                   return true;

         }

          return false;

}

 

/************************************************************************/

/* 获取一个节点的属性                                                  */

/************************************************************************/

string getAttribute(TiXmlNode * pNode)

{

         if(pNode == NULL) return "";

         //输出属性

         string msg = "";

         TiXmlElement * pElement = pNode->ToElement();

 

         TiXmlAttribute * pAttr = pElement->FirstAttribute();

         TiXmlAttribute * pNextAttr =NULL;

         string tmpAttrMsg = "[";

         if(pAttr != NULL)

         {       

                   string tmpAttrVal = "";

                   string tmpAttrName = "";                

 

                   do

                   {                                                               

                            tmpAttrVal = pAttr->Value();

                            tmpAttrName = pAttr->Name();

                            tmpAttrMsg += tmpAttrName+"=" + tmpAttrVal+",";   //各个属性之间用逗号分隔

                   }while(pAttr = pAttr->Next());

                   tmpAttrMsg = tmpAttrMsg.erase(tmpAttrMsg.find_last_of(","));

         }

         tmpAttrMsg += "]";

         msg += tmpAttrMsg;

}

 

 

/************************************************************************/

/*     在指定位置插入一个元素                                                                                                           */

/************************************************************************/

bool insertAElement(TiXmlElement * pElement)

{

         //加载一个XML的文档对象。

         TiXmlDocument *xmlDoc = new TiXmlDocument("Person.xml");

         xmlDoc->LoadFile();

 

         if(xmlDoc == NULL)           return false;

         //获得xml的头,即声明部分

         TiXmlDeclaration* decl = xmlDoc->FirstChild()->ToDeclaration();

         if(decl != NULL)

         {

                   cout << "xml文件的版本是:" << decl->Version()  << endl;

                   cout << "xml的编码格式是:" << decl->Encoding() << endl;

         }

         //获得根元素

         TiXmlElement *RootElement = xmlDoc->RootElement();

         if(RootElement != NULL)

         {

                   TiXmlNode * pNode = SelectSingleNode(xmlDoc,"name","length","100");

                   if(pNode == NULL)

                   {

                            return false;

                   }

                  

                   //创建一个Person元素并连接。

                   TiXmlElement *pNewElement = new TiXmlElement("Person");

                   if(pNewElement == NULL)

                   {

                            return false;

                   }

                   pNewElement->SetAttribute("Id","1");

                  TiXmlText *textElement = new TiXmlText("gbnn");

                   if(textElement == NULL)

                   {

                            return false;

                   }

                   pNewElement->LinkEndChild(textElement);

                   TiXmlNode * pRet = pNode->InsertBeforeChild(pNode->LastChild(),*pNewElement);

                   //TiXmlNode * pRet = pNode->LinkEndChild(pNewElement);

                   xmlDoc->Print();

                   bool b = xmlDoc->SaveFile();

                   if(b)

                   {

                            cout << "添加成功" << endl;

                            return b;

                   }

                   else

                   {

                            cout << "添加失败" << endl;

                            return false;

                   }

         }

         else

         {

                   return false;

         }

}       

 

原创粉丝点击