tinyxml使用技巧

实在是好用呀,优点比如:
1,一次装载到内存,其它地方全用引用即可,一个小指针可以是一个元素,也可是一个节(内部很多子元素)。
2,不用管理元素的内存回收,我是没看源码,号称管理的很好。一个父元素删除,它包含的所有子都释放了。
3,api较少并且,一目了然。
遍历时基本就用三个算法:
1)同级的循环(没用遍历以防会误解包括子节点处理)
//pParent当然是父了
for (TiXmlNode *pSTATE = pParent->FirstChild( “STATE” ); pSTATE; pSTATE = pSTATE->NextSibling(“STATE” ))
{}
注意:要用TiXmlNode *结构,不要用TiXmlElement*
2)当同级的到了最后一个,NextSibling()会返回个空。这时你可以用跳了。
pParent->IterateChildren( pSTATE )
3)以上两个掌握了,就可以玩遍历了。不过,要注意,走到叶子节点时,要跳级。但如果你手工跳了,可能遍历会有重复情况。这时可以使用函数的静态变量喽。可以用静态变量记住父结点。可以用静态list来存放处理过的节点,跳过重复情况。示例代码如下:
void handleExportMap(TiXmlNode * pSrc)
{
if (!pSrc ) return;

static TiXmlNode *bodyItem;

if (“FRAME_BODY” == pSrc->ValueTStr())
{
bodyItem = pSrc ;
}
static TiXmlNode *curpItem;
int t = pSrc ->Type();
printf( “type %d \n” , t);

switch (t)
{
case TiXmlNode :: TINYXML_DOCUMENT:
printf( “Document” );
break ;

case TiXmlNode :: TINYXML_ELEMENT:
printf( “Element [%s]” , pSrc ->Value());
//
if (“CONTENT” == pSrc->ValueTStr())
{
curpItem = pSrc ;
}
if (“MAP” == pSrc->ValueTStr())
{
//跳过MAP的处理
pSrc = curpItem->IterateChildren(pSrc ->Parent());

if (!pSrc )
return ;
else
printf( “Element [%s]” , pSrc ->Value());
}
if (“STATE” == pSrc->ValueTStr() && pSrc == pSrc ->Parent()->LastChild())
{
//跳过STATE的处理
//map中的state
pSrc = curpItem->IterateChildren(pSrc ->Parent()->Parent());

if (!pSrc )
return ;
else
printf( “Element [%s]” , pSrc ->Value());
}

if (“ITEM” == pSrc->ValueTStr())
{

printf( “Element [%s]” , pSrc ->Value());

if (!pSrc ->NoChildren())
{
if (!bMoveItems(pSrc ))
return ;
}

} //end if (!pSrc->NoChildren())
if (“MESSAGE” == pSrc->ValueTStr())
{
curpItem = pSrc ;
if (!bMoveItems(pSrc ))
return ;
}
break ;

case TiXmlNode :: TINYXML_COMMENT:
printf( “Comment: [%s]” , pSrc ->Value());
break ;

case TiXmlNode :: TINYXML_UNKNOWN:
printf( “Unknown” );
break ;

case TiXmlNode :: TINYXML_TEXT:
printf( “Text: [%s]\n” , pSrc ->ToText()->Value());
break ;

case TiXmlNode :: TINYXML_DECLARATION:
printf( “Declaration” );
break ;
default :
break ;
}

if (pSrc ->NoChildren())
{
pSrc = pSrc ->NextSibling();

handleExportMap( pSrc );
}
else
{
//过滤,直到合法
while (pSrc = pSrc->FirstChild())
{
handleExportMap( pSrc );

}

}
}
在这个遍历的框架基础上,可以变化和设计出你的需求了,注意,要分化任务,只做遍历,和只做节点的处理,不要混在一起,不然,一个bug两三天呀。上面的bMoveItems就是当定位到了ITEM节点时,我调用其它的业务处理。因为,人只关注ITEM节点,所以它有一些子节点MAP或子子节点STATE,都在上面一一跳过了。

最后,附上“米”,好“下锅”,注意层次。
<?xml version=”1.0″ encoding=”UTF-8″ ?>
<!– edited with XMLSpy v2013 (http://www.altova.com) by () –>
<LINE ID=”11″ VERSION=”1″>
<FRAME_HEADER>
<ITEM ID=”system_id” LENGTH=”1″ CURPOS=”0″ />
<ITEM ID=”total_length” LENGTH=”2″ CURPOS=”1″ MAX_VALUE=”1025″ />
<ITEM ID=”multi_flag” LENGTH=”1″ CURPOS=”3″ DEFAULT=”0″ />
</FRAME_HEADER>
<FRAME_BODY>
<MESSAGE ID=”NETWORK_ALIVE_STATUS” TYPE=”1″ TRANS=”O2N”>
<ITEM ID=”message_length” LENGTH=”2″ CURPOS=”4″ DESC=”消息长度” MIN_VALUE=”13″ interal_index=”1″ />
<ITEM ID=”time” LENGTH=”4″ CURPOS=”6″ DESC=”时间” FORMAT=”HHMMSS” interal_index=”2″>
<MAP NID=”time” MODE=”1″ SAME=”Y” NINDEX=”2″ KEY=”time|6|4″ DESC=”时间” EX_CODE_KEY=”” />
</ITEM>
<ITEM ID=”version” LENGTH=”2″ CURPOS=”10″ DESC=”版本” DEFAULT=”01H” interal_index=”3″ />
<ITEM ID=”msg_id” LENGTH=”2″ CURPOS=”12″ DESC=”报文ID” interal_index=”4″ />
<CONTENT ID=”data0″ DEFAULT_LEN=”3″>
<ITEM ID=”line_id” LENGTH=”2″ CURPOS=”14″ DESC=”线路号” interal_index=”5″>
<MAP NID=”line_id” MODE=”1″ SAME=”Y” NINDEX=”5″ KEY=”line_id|14|2″ EX_CODE_KEY=”” />
</ITEM>
<ITEM ID=”status” LENGTH=”1″ CURPOS=”16″ DESC=”状态字节:1:代表与当前线路号的信息源(server)连接正常;0:代表断开。” interal_index=”6″>
<MAP NID=”xt_pkg” MODE=”1″ SAME=”N” NINDEX=”6″ KEY=”xt_pkg|16|1″ EX_CODE_KEY=””>
<STATE ID=”11_STATUS_CODE_1″ RAWVALUE=”0x00″ HINT=”通信中断” SAME=”Y”>0x80</STATE>
<STATE ID=”11_STATUS_CODE_2″ RAWVALUE=”0x01″ HINT=”通信正常” SAME=”Y”>0x02</STATE>
</MAP>
</ITEM>
</CONTENT>
</MESSAGE>
<MESSAGE ID=”LOAD_DEVICE_STATUS” TYPE=”1″ TRANS=”N2O”>
<ITEM ID=”message_length” LENGTH=”2″ CURPOS=”4″ DESC=”消息长度” MIN_VALUE=”12″ interal_index=”1″ />
<ITEM ID=”time” LENGTH=”4″ CURPOS=”6″ DESC=”时间” FORMAT=”HHMMSS” interal_index=”2″ />
<ITEM ID=”version” LENGTH=”2″ CURPOS=”10″ DESC=”版本” DEFAULT=”01H” interal_index=”3″ />
<ITEM ID=”msg_id” LENGTH=”2″ CURPOS=”12″ DESC=”报文ID” interal_index=”4″ />
<CONTENT ID=”data0″ DEFAULT_LEN=”2″>
<ITEM ID=”line_id” LENGTH=”2″ CURPOS=”14″ DESC=”线路号” interal_index=”5″ />
</CONTENT>
</MESSAGE>
</MESSAGE>
</FRAME_BODY>
</LINE>

保存和另存,一个TiXmlDocument的SaveFile()函数就搞定了。
生成新的XML时,会用一个api就成了。parent->LinkEndChild(TiXmlNode *);根据不用我解释了吧。加同级,用parent()找父指针嘛。

发表回复