tinyxml源码解析(上)
转载于:http://www.cnblogs.com/marchtea/archive/2012/11/09/2762669.html
前言:
前段时间做功能可行性的时候简单的使用了tinyxml。在sourceforge下载的时候,看到老外对于这个库的评价很高,因此就有冲动进行学习这么一个优秀的框架。简单查看了代码,代码量也不是很大。刚好事情做的差不多,索性就学习学习好了。第一次尝试阅读正式的框架,水平也不是很好,可能多少会有点出错,要是有错误还望多包涵并且提出来,一起进步哈。
文章打算分为三部分,第一部分介绍了TiXmlBase,TiXmlNode这两个基类,第二部分详细了介绍了代表节点的几个类,第三部分介绍了库中提供的一些工具类。
正言:
先简单介绍下tinyxml吧。在我的前一篇文章也介绍了下,还有使用方法。tinyxml是一款轻量级的xml parser。其目的在于在提供基本的xml操作的同时保持一个简单的用户接口供用户使用。其能实现基本的xml的特性。如遍历xml文件,获取节点等。至于dtd,xstl等特性并不支持。详细可以查看我的上一篇文章。
tinyxml整体的类的架构图如下:
TiXmlBase是所有tinyxml里面的元素的基类,其提供了一些基本的操作和属性。一会分析。
xml中的节点的所有父类皆为TiXmlNode,其可以转化成任意一种特定的节点。而对于我们的element节点中的属性来说,其在构造时也是做为element的子节点来构建的,不过由于其只能出现在element中,因此并没有继承自TiXmlNode。
TiXmlNode也提供了一些基本的节点操作,如获取子节点,插入子节点等。
这篇文章将主要讲解TiXmlBase以及TiXmlNode。
TiXmlBase:
先讲下所有类的基类TiXmlBase吧。
这里是头文件的内容。
读完头文件,来看看具体的实现
首先是之前提到的entity,定义在tinyxmlparser.cpp
//定义了xml中的entity数组.用于函数转化 TiXmlBase::Entity TiXmlBase::entity[ TiXmlBase::NUM_ENTITY ] = { { "&", 5, '&' }, { "<", 4, '<' }, { ">", 4, '>' }, { """, 6, '\"' }, { "'", 6, '\'' } };
接下来就是说到的EncodeString了.
SkipWhiteSpace:这个实在没什么好说的.
1 //折叠又打不开了.就不折叠了 2 const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding ) 3 { 4 if ( !p || !*p ) 5 { 6 return 0; 7 } 8 if ( encoding == TIXML_ENCODING_UTF8 ) 9 { 10 while ( *p ) 11 { 12 const unsigned char* pU = (const unsigned char*)p; 13 14 // 跳过ms的UTF8头 15 if ( *(pU+0)==TIXML_UTF_LEAD_0 16 && *(pU+1)==TIXML_UTF_LEAD_1 17 && *(pU+2)==TIXML_UTF_LEAD_2 ) 18 { 19 p += 3; 20 continue; 21 } 22 else if(*(pU+0)==TIXML_UTF_LEAD_0 23 && *(pU+1)==0xbfU 24 && *(pU+2)==0xbeU ) 25 { 26 p += 3; 27 continue; 28 } 29 else if(*(pU+0)==TIXML_UTF_LEAD_0 30 && *(pU+1)==0xbfU 31 && *(pU+2)==0xbfU ) 32 { 33 p += 3; 34 continue; 35 } 36 37 //仍然采用了英文的,ansi的方式进行判断. 38 if ( IsWhiteSpace( *p ) ) 39 ++p; 40 else 41 break; 42 } 43 } 44 else 45 { 46 //对于其他编码也是 47 while ( *p && IsWhiteSpace( *p ) ) 48 ++p; 49 } 50 51 return p; 52 }
ReadName
ReadText: 读取属性中的值,读取<></>之间的文本.
StringEqual:就是一个比较函数,比较简单.
ConvertUTF32ToUTF8:这是个转化工具,我也不大懂.根据编码规则应该就能实现.贴出来吧.
看完了最基础的TiXmlBase类之后,也能感觉到,这个基类就是提供了基本的处理工具的作用,以及为后续的类设定了一些虚函数供后续继承.而且由于是纯虚类,因此也不能声明TiXmlBase的对象.
接下来就看看还具有一定实用性的TiXmlNode类吧.
这个类是除了TiXmlAttribute之外的所有元素类的父类,里面提供了对于xml对象基本的操作.如遍历子节点,访问兄弟节点,插入,删除节点等操作.这样在后面的子类继承时,就不用考虑这些操作了.
先看看头文件吧.
在头文件中,我们可以看到,TiXmlNode提供了很多遍历,查找子节点的函数.为后续继承的子类搭好了树结构的基础.同时通过私有化复制构造函数以及复制操作符的方式避免意外的复制从而导致错误以及额外的开销.
来看具体的实现.我们就挑几个重要的函数看看好了.
首先是遍历子节点的操作IterateChildren
至于带value版本的IterateChildren,也调用了其他的函数
而带value版本的FirstChild其实也没什么神秘的,就是对链表的操作而已.
那那些NextSibling等等其实也没有什么好深究的了.还是看看变动性操作吧.
LinkEndChild
分析之后可以看出整体采用的就是双向链表来组织数据的.其他的代码就不用怎么展示了,大多都是链表的操作.
总结:
第一节主要就介绍两个基类及其成员函数.整体显得会比较枯燥,而且看完还是不明白整体tinyxml的处理方式.
详细的tinyxml处理流程我将在第二节进行说明.有什么疑问欢迎交流.第一次写这样的文章,写得不是很好,望大家多包涵.