无氏木

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

用C++解析XML一直用的tinyxml,轻便,简单。这里记录下一些自己的使用方法与心得。

对于用tinyxml解析xml,我一般只有三个步骤:

  1. 加载
  2. 获取节点
  3. 读取内容

1.加载

Tinyxml是由一堆类构成的,而加载用到的类是TiXmlDocument。要解析目标XML前都要将目标XML加载到TiXmlDocument对象中,之后的所有操作都将从TiXmlDocument对象出发,包括目标字符串和文件。

加载字符串用LoadFile(const char* buf);

加载文件用Parse(const char* filename);

具体的可去看函数声明

如下,是个有个简单的文档,存于名为class.xml的文档中

1 <?xml version="1.0" encoding="UTF-8" ?>
2 <class>
3     <student ID="1" ID2="test">
4         <Sex></Sex>
5         <Name>班长</Name>
6     </student>
7     <student ID="2"></student>
8 </class>

我创建一个TiXmlDocument,此文介绍全为加载此文档前题下,当然如果是从网络或是别处传入的,只要直接传入内存地址指针就成了。

TiXmlDocument* doc = new TiXmlDocument();
doc->LoadFile("./class.xml");

当然,在使用前最重要的判断指针是否为NULL,之后讲的东西也一样,这是很重要的一点

if(doc == NULL){return;}

2.获取节点

当加载完成了,便开始解析了,而解析的过程,无非是从一个节点元素开始,往两个方面走,一个向子节点方向深入,一个往兄弟节点平移,而根据需求决定要不要取节点的值。一会详述。

首先我们解析下xml声明,而声明中有用的便是 编码方式。TiXmlDeclaration类表示声明,从doc中通过ToDeclaration()获得,而编码方式则是decl的Encoding(),返回的是const char*;

//获取文档的声明
TiXmlDeclaration* decl = doc->ToDeclaration(); 
if ( NULL != decl )
    {
        std::string encoding = decl->Encoding(); //这里会返回“UTF-8"
    }

接下来,开始解析元素。一般XML都有一个根元素,根元素是所有元素的父元素。根元素可以由以下方法获得:

TiXmlElement* root = doc->RootElement();

这个方法可以获得根元素,此元素便是<class>了。

TiXmlElement类,表示元素类,是解析过程中的用的最多的一个类,可以表示所有<>内的元素,当然包括根元素。这里root是指向根元素,而如果你并不知道根元素的名称,可以能过root->Value()获得。而如果你知道这个XML文件的根节点名,笔者用XML一般做传输协议,基本都是知道整个XML的结构的,我推荐另一个方法获取根节点。

TiXmlElement* NodeRoot = doc->FirstChildElement("class");

上行代码表示获取doc的第一个class子节点,因为一开始我们就知道这个XML是以<class>为根节点,这样做不仅可以获取根节点,而且可以验证是不是以class为根节点的。

获取根节点成功后,接下来便是获取student节点了:

//不知道具体节点名
 TiXmlElement* NodeStudent = NodeRoot->FirstChildElement();
std::cout << NodeStudent->Value << std::endl; //这里输出节点名,即student
//知道节点名 TiXmlElement* NodeStudent = NodeRoot->FirstChildElement("student");

 当前NodeStrudnt是指向<student ID="1" ID2="test">,而ID,ID2是元素student的属性,“1“,”test"是属性的值,下方的<sex><name>是子节点,也是元素。

想要获取ID=1可用以下代码

TiXmlAttribute* attr = NodeStudent->FirstAttribute();
if(NULL != attr)
{
      std::cout << attr->Name() << endl;     //这时输出ID
      std::cout << attr->Value() << endl;     //这里输出1
}      
attr = attr->Next(); //这里指向第二个属性,attr->Next()操作时是不会自增长的,只是返回下一个属性,所以还要自己赋值
std::cout << attr->Value();    //这里当没有ID2属性时,会抛出异常

想要获得<Sex>只能通过父节点获得,而<Name>则可以同时通过兄弟节点获得

//先通过父节点获取
//不知道具体节点名,指向<Sex>
 TiXmlElement* NodeSex = NodeStudent->FirstChildElement();
//知道节点名,指向<class>
 TiXmlElement* NodeName = NodeStudent->FirstChildElement("Name");
//通过兄弟节点指向<class>
TiXmlElement* NodeName = NodeSex->NextSiblingElement();
TiXmlElement* NodeName = NodeSex->NextSiblingElement("Name");

而如果想获得节点里的文本信息,可以通过以下方法获得,当然得是元素不为NULL的情况下

//1.可以通过GetText,缺点是当文本信息为空时,会抛了异常
std::cout << NodeSex->GetText() << endl;        //输出“男”
std::cout << NodeName->GetText() << endl;    //输出“班长“
//2.可以过能GetChild判断是否有子文本,然后通过Value()获得
TiXmlNode* text = nodeSex->FirstChild();
if( NULL != text)
     std::cout << text.Value() <<endl;       //输出”男“

如果有很多学生要遍历都可以

while(NULL != NodeStudent)
{
  ...//相应的解析,取值  

  NodeStudent= NodeStudent->NextSiblingElement("stduent");
}

3.获取内容

第二部分好像已经讲过了,再总结下

获取元素名为  Value()

获取属性名 Name(),属性值Value()

获取文本信息:GetText(),这里要注意不能为空或者通过TiXmlNode的Value获取

 

以上,就是本人解析XML的常用方法,初稿,之后有时间再编辑修改,  BY  WenHY  无氏木

注意点:

1.XML是大小写区分的

2.一定要注意检察获取的东西是否为空

3.最后要释放doc

 

 

 

 

posted on 2013-08-07 21:39  无氏木  阅读(498)  评论(0编辑  收藏  举报