tinyxml 是开源c++软件, 递归代码的特点: 易写易读难调.
Print()函数是一个重载函数,每个对象都有自己的Print() 函数.
doc print, 就是把每个结点都print 一遍。
void TiXmlDocument::Print( FILE# cfile, int depth ) const
{
for ( const TiXmlNode# node=FirstChild(); node; node=node->NextSibling() )
{
node->Print( cfile, depth );
fprintf( cfile, “\n” );
}
}
声明,注释,文本都是结点,这些结点打印很简单,打印出来就可以了。
这是关键,因为它牵扯到递归。也牵扯属性, 代码写的看起来很简单,因为是递归,调试起来比较复杂.
分析:
4.1. 首先根据depth 深度打印空格
4.2. 然后打印元素开始<加value
4.3. 如果有属性,再打印属性
4.4. 如果没有child,则打印 /> 结束
4.5. 如果有child, 如果child结点不包含文本,则先打印一个回车,再打印child 结点,深度会加1(这里是递归)
4.6. 打印换行后再打印对齐空格,再打印尾巴加value加>来结束
这里面对于只有一个child 的情况,有一个打印上的优化,少打一个回车使看起来更舒服.
属性不是一个node. 所以它不在上面doc.Print 的循环中,但它是元素的属性
属性是键值对,打印它的name,value即可,value需要用双引号括起来, 如果value中包含双引号,那就用单引号括起来。
while ( p && #p )
{
TiXmlNode# node = Identify( p, encoding ); // 先判断出是哪种类型的结点. 都用其基类TiXmlNode来指向具体的类型
if ( node )
{//Parse 是基类TiXmlBase的虚函数(接口函数), TiXmlNode 并无Parse函数,但具体的Node类型实现了Pase函数
p = node->Parse( p, &data, encoding );
LinkEndChild( node ); //把分析到的node 链接起来
}
}
首先必需以< 开头, 然后以 头
2.1 : 声明的分析. 它需要调用属性分析,分析出version,encoding,standalone的值
2.2 : 注释的分析. 它把
为止所有的东西都保存到value中
2.3 : 元素的分析.
2.3.1: 首先它要读取名字到value中
2.3.2: 如果后面跟的是/> ,则结束分析,返回
2.3.3: 如果后面跟的是> ,则要读取value 到 data,然后后面应该是endtag及>否则格式错误
2.3.4: 否则跟的是属性, 则读取属性,并把属性加到属性集中,再继续分析.
声明一个属性对象,然后进行分析.
读取名字ReadName(),然后碰到一个’=',然后读取文本ReadText(), 分别存储到name 和 value
4.1 如果不是<开始,则说明是一个文本,
TiXmlText# textNode = new TiXmlText( "" );
p = textNode->Parse( p, data, encoding );
LinkEndChild( textNode );
4.2 是< 开始, 递归调用. 得到一个结点表示,分析
TiXmlNode# node = Identify( p, encoding );
p = node->Parse( p, data, encoding );
LinkEndChild( node );
参考代码:
#include
#include
using namespace std;
#include "tinyxml.h"
int main()
{
const char* demoStart =
"\n"
""
"\n"
"\n"
"- 游香山
"
"- 逛故宫
"
"- 去
长城 "
"";
//代码简单,跟踪调试才是硬道理!
TiXmlDocument doc( "demotest.xml" ); //创建一个文档,名称为demotest.xml
doc.Parse( demoStart ); //将字符串分析进该文档,成为一个个结点 (递归分析,比较麻烦!)
if ( doc.Error() )
{
printf( "Error in %s: %s\n", doc.Value(), doc.ErrorDesc() );
exit( 1 );
}
doc.Print(); //文档向屏幕输出, 递归打印!(比较麻烦)
// doc.SaveFile(); //保留文档到文件
return 0;
}