tinyXML源码刨析(下)--解析树的使用

在上一篇文章中分析了如何把XML文件解析为一棵树,现在就来分析一下tinyXML是如何利用这个树输出XML文件,以及更进一步的更改XML文件的内容的。
首先介绍两个用于输出的工具类,以及一个遍历树的函数:

  • TiXmlVisitor ,这个类是一个基类,没有数据成员,只定义了一些虚函数。
  • TiXmlPrinter,是TiXmlVisitor的派生类,重载了TiXmlVisitor中的visit函数,根据要打印节点的类型采取不同的打印策略打印,并增加了5个数据成员用来设置输出格式。
	int depth;//结点距根节点的层数
	bool simpleTextPrint;//是否
	TIXML_STRING buffer;//缓冲区
	TIXML_STRING indent;//缩进
	TIXML_STRING lineBreak;//换行符
  • Accept( TiXmlVisitor* visitor )函数,接受一个TiXmlVisitor指针,然后调用TiXmlVisitor中针对不同的结点的不同打印方法。Accept函数存在的目的就是为了确定不同的节点类型,以方便TiXmlvisitor调用对应的方法。

document的Accept()函数调用了document版本的VisitEnter函数,然后遍历document的孩子节点,并对不同的节点分别调用对应版本的Accept()和visit函数,输出节点包含的内容

仍然以下面这个解析树为例

TiXmlDocument     "demo.xml"
            TiXmlDeclaration   "version='1.0'" "standalone=no"
            TiXmlComment    " Our to do list data"
            TiXmlElement    "ToDo"
                       TiXmlElement   "Item" Attribtutes: priority = 1
                                TiXmlText   "Go to the "
                                TiXmlElement  "bold"
                                     TiXmlText  "Toy store!"
                       TiXmlElement   "Item" Attributes: priority=2
             TiXmlText   "Do bills"

假设TiXmlDocument doc 中已经生成好一棵解析树。

  1. 首先生成一个TiXmlPrinter printer;默认构造函数就好,以默认的方式打印
  2. 然后调用TiXmlDocument 的Accept函数–doc.Accept(&printer);告诉printer,是要打印document中的内容。这个版本的Accept遍历document的子节点,分别调用各个子节点版本的Accept函数。如下所示
bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const
{
	if ( visitor->VisitEnter( *this ) )
	{
		for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
		{
			if ( !node->Accept( visitor ) )
				break;
		}
	}
	return visitor->VisitExit( *this );
}
  1. for循环第一次node类型为 TiXmlDeclaration,调用 TiXmlDeclaration版本的Accept,再调用visit,把 TiXmlDeclaration中保存的version,encoding,standalone按照次序打印出来。
  2. for循环第二次node的类型为TiXmlComment ,调用TiXmlComment 版本的Accept和visit,把TiXmlComment 中的value打印出来即可。
  3. for循环第三次node的类型为 TiXmlElement, TiXmlElement版本的Accept和TiXmlDocument的有些类似,都需要遍历自己的子节点,但是TiXmlElement需要先把Element的值打印出来,然后再遍历。
    TiXmlElement中有几个点需要注意:
    首先每进去一层Element,都需要多打几个空格,表示不同的层次有不同的缩进。
    如果Element中没有子节点,则直接输出一个对尖括号,不必像XML标准格式一样输出开始和结束标志。例如输出< Item Attributes: priority=2/>而不是< Item Attributes: priority=2> < Item/>
    Element和document这两种内部包含其他结点的类型,最后要VisitEnter进去,再VisitExit出去。原因是,内部不含节点的类型开始标志"< Item"和结束标志 “/>“靠的很近,可以直接输出。而Element和document的必须先输出完内部节点之后才能找到”/>”,所以必须单独实施退出操作。

在了解了解析树是如何生成,以及如何打印之后,如何添加节点,更改节点内容就是水到渠成的事了,这里就不再赘述。

遇到的问题:

  1. document的Accept()函数中
if ( !node->Accept( visitor ) )

这一句在node=NULL的情况下不会报错吗?
2.为什么TiXmlVisitor中成员函数要定义成virtual?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值