如何利用tinyxml操縱xml及注意問(wèn)題
更新時(shí)間:2013年01月03日 12:10:19 作者:
這篇博客,我們?cè)敿?xì)講述如何利用tinyxml操縱xml。以及在操作的過(guò)程中,我們應(yīng)該注意的問(wèn)題
在上篇博客中,大概了解了tinyxml工具的架構(gòu),那這篇博客,我們?cè)敿?xì)講述如何利用tinyxml操縱xml。以及在操作的過(guò)程中,我們應(yīng)該注意的問(wèn)題。
首先把tinyxml源文件導(dǎo)入自己的工程中,效果如下:


若您的系統(tǒng)是win7或office是2007以上的,添加文件這個(gè)功能是不能用的,結(jié)果是:或直接崩潰?;驔](méi)反應(yīng)。解決方案如下:
http://www.dbjr.com.cn/article/32996.htm
環(huán)境準(zhǔn)備好了,那么我們開始動(dòng)手操作吧。正如對(duì)數(shù)據(jù)庫(kù)表操作一樣---增刪改查。根據(jù)此邏輯,那就從增(創(chuàng)建)開始。
創(chuàng)建的格式如下:
<Persons>
<Person>
<name>lhy</name>
<age>22</age>
</Person>
</Persons>
上篇博客中,我們也介紹了tinyxml解析器中的所有的類以及類之間的關(guān)系。
創(chuàng)建上述格式的xml,代碼如下:
//創(chuàng)建一個(gè)XML的文檔對(duì)象。
TiXmlDocument *myDocument = new TiXmlDocument();
//創(chuàng)建一個(gè)根元素并連接。
TiXmlElement *RootElement = new TiXmlElement("Persons");
myDocument->LinkEndChild(RootElement);
//創(chuàng)建一個(gè)Person元素并連接。
TiXmlElement *PersonElement = new TiXmlElement("Person");
RootElement->LinkEndChild(PersonElement);
//創(chuàng)建name元素、age元素并連接。
TiXmlElement *NameElement = new TiXmlElement("name");
TiXmlElement *AgeElement = new TiXmlElement("age");
PersonElement->LinkEndChild(NameElement);
PersonElement->LinkEndChild(AgeElement);
//設(shè)置name元素和age元素的內(nèi)容并連接。
TiXmlText *NameContent = new TiXmlText("lhy");
TiXmlText *AgeContent = new TiXmlText("22");
NameElement->LinkEndChild(NameContent);
AgeElement->LinkEndChild(AgeContent);
myDocument->SaveFile("d:\\lhy\\xml.txt");//保存到文件
只要搞清xml中節(jié)點(diǎn)之間的關(guān)系,創(chuàng)建不是問(wèn)題。說(shuō)白了就是一種輩分關(guān)系。
創(chuàng)建搞定了,但是作為C++程序猿,寫完之后,總感覺(jué)有點(diǎn)別扭,總感覺(jué)哪不對(duì)勁。你是否也看出其中存在的貓膩?
對(duì)了,些許的代碼中有大量的New指針。在C++中可沒(méi)有java中的垃圾回收機(jī)制,必須自己來(lái)處理這些廢棄的垃圾。但是代碼中卻沒(méi)有Delete語(yǔ)句?
上網(wǎng)查了資料,發(fā)現(xiàn)很多創(chuàng)建代碼中,都沒(méi)有Delete語(yǔ)句?難道是大家都是復(fù)制粘貼?還是tinyxml在搞怪?
我總結(jié)了以下幾點(diǎn),但是最后在開發(fā)的過(guò)程中仍是疑問(wèn),但是開發(fā)的過(guò)程中,沒(méi)有出現(xiàn)問(wèn)題,所以我的程序就暫時(shí)如此了。
說(shuō)法一:很多文章中,都是new沒(méi)有delete,是因?yàn)閠inyxml可以自動(dòng)釋放,自動(dòng)銷毀指針,無(wú)需開發(fā)者手動(dòng)釋放。
質(zhì)疑:new出來(lái)的可以自動(dòng)釋放?new出來(lái)說(shuō)明是在堆上創(chuàng)建的,什么時(shí)候會(huì)自動(dòng)釋放?程序結(jié)束時(shí),自動(dòng)釋放?那怎么判斷程序結(jié)束呢?(在一個(gè)模塊中如何析構(gòu)另一個(gè)模塊中的內(nèi)存區(qū)域,我們后面會(huì)詳談),所以這種說(shuō)法不攻自破。
既然tinyxml中有自毀功能,那我們查詢其源代碼,發(fā)現(xiàn)果真如此,tinyxml中在析構(gòu)函數(shù)中,有相應(yīng)的指針釋放。但是并不是每個(gè)節(jié)點(diǎn)如此的。
源碼中的詳情:
TiXmlNode::~TiXmlNode()
{
TiXmlNode* node = firstChild;
TiXmlNode* temp = 0;
while ( node )
{
temp = node;
node = node->next;
delete temp;
}
}
void TiXmlNode::Clear()
{
TiXmlNode* node = firstChild;
TiXmlNode* temp = 0;
while ( node )
{
temp = node;
node = node->next;
delete temp;
}
firstChild = 0;
lastChild = 0;
}
我們也知道tinyxml中的類之間存在繼承關(guān)系。
那我們看tinyxml中的TixmlElement類:
TiXmlElement::~TiXmlElement()
{
ClearThis();
}
void TiXmlElement::ClearThis()
{
Clear();
while( attributeSet.First() )
{
TiXmlAttribute* node = attributeSet.First();
attributeSet.Remove( node );
delete node;
}
}
因?yàn)門ixmlElement是繼承TiXmlNode.但是在TiXmlDocument中并沒(méi)有發(fā)現(xiàn)TiXmlDocument類的析構(gòu)函數(shù)。
第二種說(shuō)法:TiXmlDocument對(duì)象就是這棵樹的根結(jié)點(diǎn), 在一個(gè)完整的文檔中, 除了它, 其余結(jié)點(diǎn)必須都是它的后代, 所以TinyXml用了一個(gè)很巧妙的方法來(lái)析構(gòu)每一個(gè)結(jié)點(diǎn)所對(duì)應(yīng)的對(duì)象 ---- 每個(gè)結(jié)點(diǎn)的析構(gòu)任務(wù)都委托給了它的父親, 這樣只要保證父親被正確析構(gòu), 或者調(diào)用了父親的Clear函數(shù), 它的所有后代都會(huì)被正確的析構(gòu), 所以對(duì)整個(gè)文檔來(lái)說(shuō)只要TiXmlDocument對(duì)象被正確析構(gòu)即可。
在創(chuàng)建的上述代碼中,我們發(fā)現(xiàn),所有的節(jié)點(diǎn)都是掛在根節(jié)點(diǎn)之下的。
其實(shí)這句代碼: myDocument->LinkEndChild(RootElement);使用了多態(tài)方式。類之間的關(guān)系如下:
并且LinkEndChild源代碼如下:它是父類TiXmlNode中的方法
TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
{
assert( node->parent == 0 || node->parent == this );
assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() );
if ( node->Type() == TiXmlNode::DOCUMENT )
{
delete node;
if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
return 0;
}
node->parent = this;
node->prev = lastChild;
node->next = 0;
if ( lastChild )
lastChild->next = node;
else
firstChild = node;// it was an empty list.
lastChild = node;
return node;
}
這樣的話:則只要?jiǎng)h除根節(jié)點(diǎn),在程序中myDocument,就相當(dāng)于把刪除了TiXmlNode,相當(dāng)于調(diào)用了TiXmlNode的析構(gòu)函數(shù)。
質(zhì)疑:網(wǎng)上說(shuō)這種方式,析構(gòu)是從葉子到樹根。根據(jù)TiXmlNode中的析構(gòu)函數(shù),我們可以得出,是從樹根到葉子。
但是我們?cè)贒elete myDocument時(shí),應(yīng)該注意一點(diǎn):
創(chuàng)建文檔時(shí),也就是程序段中的myDocument。若是從堆上創(chuàng)建,則需需要手動(dòng)釋放。如我們上述的片段中,就是在堆上創(chuàng)建的。
TiXmlDocument *myDocument=new TiXmlDocument ();
若是從棧上創(chuàng)建,則不須我們手動(dòng)釋放,而是程序自動(dòng)調(diào)用析構(gòu)函數(shù)。同時(shí)我們應(yīng)該注意,其他的元素必須在堆上創(chuàng)建。因?yàn)樵赥iXmlNode析構(gòu)函數(shù)中,是delete的,但是棧上的東東是不須delete,所以除了根節(jié)點(diǎn)之外連接的后代節(jié)點(diǎn)是必須從堆上創(chuàng)建。
經(jīng)過(guò)我們解釋,明白tinyxml中的原理了嗎?只要理解了tinyxml中的類的作用以及類之間的關(guān)系,看源碼是沒(méi)問(wèn)題滴哦。
這篇博客根據(jù)創(chuàng)建xml小demo解釋了其中存在的疑問(wèn)。那下篇博客中我們會(huì)根據(jù)解析xml來(lái)答疑解析中存在的問(wèn)題。
首先把tinyxml源文件導(dǎo)入自己的工程中,效果如下:

實(shí)際上,直接添加文件到工程中:如下:

若您的系統(tǒng)是win7或office是2007以上的,添加文件這個(gè)功能是不能用的,結(jié)果是:或直接崩潰?;驔](méi)反應(yīng)。解決方案如下:
http://www.dbjr.com.cn/article/32996.htm
環(huán)境準(zhǔn)備好了,那么我們開始動(dòng)手操作吧。正如對(duì)數(shù)據(jù)庫(kù)表操作一樣---增刪改查。根據(jù)此邏輯,那就從增(創(chuàng)建)開始。
創(chuàng)建的格式如下:
復(fù)制代碼 代碼如下:
<Persons>
<Person>
<name>lhy</name>
<age>22</age>
</Person>
</Persons>
上篇博客中,我們也介紹了tinyxml解析器中的所有的類以及類之間的關(guān)系。
創(chuàng)建上述格式的xml,代碼如下:
復(fù)制代碼 代碼如下:
//創(chuàng)建一個(gè)XML的文檔對(duì)象。
TiXmlDocument *myDocument = new TiXmlDocument();
//創(chuàng)建一個(gè)根元素并連接。
TiXmlElement *RootElement = new TiXmlElement("Persons");
myDocument->LinkEndChild(RootElement);
//創(chuàng)建一個(gè)Person元素并連接。
TiXmlElement *PersonElement = new TiXmlElement("Person");
RootElement->LinkEndChild(PersonElement);
//創(chuàng)建name元素、age元素并連接。
TiXmlElement *NameElement = new TiXmlElement("name");
TiXmlElement *AgeElement = new TiXmlElement("age");
PersonElement->LinkEndChild(NameElement);
PersonElement->LinkEndChild(AgeElement);
//設(shè)置name元素和age元素的內(nèi)容并連接。
TiXmlText *NameContent = new TiXmlText("lhy");
TiXmlText *AgeContent = new TiXmlText("22");
NameElement->LinkEndChild(NameContent);
AgeElement->LinkEndChild(AgeContent);
myDocument->SaveFile("d:\\lhy\\xml.txt");//保存到文件
只要搞清xml中節(jié)點(diǎn)之間的關(guān)系,創(chuàng)建不是問(wèn)題。說(shuō)白了就是一種輩分關(guān)系。
創(chuàng)建搞定了,但是作為C++程序猿,寫完之后,總感覺(jué)有點(diǎn)別扭,總感覺(jué)哪不對(duì)勁。你是否也看出其中存在的貓膩?
對(duì)了,些許的代碼中有大量的New指針。在C++中可沒(méi)有java中的垃圾回收機(jī)制,必須自己來(lái)處理這些廢棄的垃圾。但是代碼中卻沒(méi)有Delete語(yǔ)句?
上網(wǎng)查了資料,發(fā)現(xiàn)很多創(chuàng)建代碼中,都沒(méi)有Delete語(yǔ)句?難道是大家都是復(fù)制粘貼?還是tinyxml在搞怪?
我總結(jié)了以下幾點(diǎn),但是最后在開發(fā)的過(guò)程中仍是疑問(wèn),但是開發(fā)的過(guò)程中,沒(méi)有出現(xiàn)問(wèn)題,所以我的程序就暫時(shí)如此了。
說(shuō)法一:很多文章中,都是new沒(méi)有delete,是因?yàn)閠inyxml可以自動(dòng)釋放,自動(dòng)銷毀指針,無(wú)需開發(fā)者手動(dòng)釋放。
質(zhì)疑:new出來(lái)的可以自動(dòng)釋放?new出來(lái)說(shuō)明是在堆上創(chuàng)建的,什么時(shí)候會(huì)自動(dòng)釋放?程序結(jié)束時(shí),自動(dòng)釋放?那怎么判斷程序結(jié)束呢?(在一個(gè)模塊中如何析構(gòu)另一個(gè)模塊中的內(nèi)存區(qū)域,我們后面會(huì)詳談),所以這種說(shuō)法不攻自破。
既然tinyxml中有自毀功能,那我們查詢其源代碼,發(fā)現(xiàn)果真如此,tinyxml中在析構(gòu)函數(shù)中,有相應(yīng)的指針釋放。但是并不是每個(gè)節(jié)點(diǎn)如此的。
源碼中的詳情:
復(fù)制代碼 代碼如下:
TiXmlNode::~TiXmlNode()
{
TiXmlNode* node = firstChild;
TiXmlNode* temp = 0;
while ( node )
{
temp = node;
node = node->next;
delete temp;
}
}
void TiXmlNode::Clear()
{
TiXmlNode* node = firstChild;
TiXmlNode* temp = 0;
while ( node )
{
temp = node;
node = node->next;
delete temp;
}
firstChild = 0;
lastChild = 0;
}
我們也知道tinyxml中的類之間存在繼承關(guān)系。
那我們看tinyxml中的TixmlElement類:
復(fù)制代碼 代碼如下:
TiXmlElement::~TiXmlElement()
{
ClearThis();
}
void TiXmlElement::ClearThis()
{
Clear();
while( attributeSet.First() )
{
TiXmlAttribute* node = attributeSet.First();
attributeSet.Remove( node );
delete node;
}
}
因?yàn)門ixmlElement是繼承TiXmlNode.但是在TiXmlDocument中并沒(méi)有發(fā)現(xiàn)TiXmlDocument類的析構(gòu)函數(shù)。
第二種說(shuō)法:TiXmlDocument對(duì)象就是這棵樹的根結(jié)點(diǎn), 在一個(gè)完整的文檔中, 除了它, 其余結(jié)點(diǎn)必須都是它的后代, 所以TinyXml用了一個(gè)很巧妙的方法來(lái)析構(gòu)每一個(gè)結(jié)點(diǎn)所對(duì)應(yīng)的對(duì)象 ---- 每個(gè)結(jié)點(diǎn)的析構(gòu)任務(wù)都委托給了它的父親, 這樣只要保證父親被正確析構(gòu), 或者調(diào)用了父親的Clear函數(shù), 它的所有后代都會(huì)被正確的析構(gòu), 所以對(duì)整個(gè)文檔來(lái)說(shuō)只要TiXmlDocument對(duì)象被正確析構(gòu)即可。
在創(chuàng)建的上述代碼中,我們發(fā)現(xiàn),所有的節(jié)點(diǎn)都是掛在根節(jié)點(diǎn)之下的。
其實(shí)這句代碼: myDocument->LinkEndChild(RootElement);使用了多態(tài)方式。類之間的關(guān)系如下:
并且LinkEndChild源代碼如下:它是父類TiXmlNode中的方法
復(fù)制代碼 代碼如下:
TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
{
assert( node->parent == 0 || node->parent == this );
assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() );
if ( node->Type() == TiXmlNode::DOCUMENT )
{
delete node;
if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
return 0;
}
node->parent = this;
node->prev = lastChild;
node->next = 0;
if ( lastChild )
lastChild->next = node;
else
firstChild = node;// it was an empty list.
lastChild = node;
return node;
}
這樣的話:則只要?jiǎng)h除根節(jié)點(diǎn),在程序中myDocument,就相當(dāng)于把刪除了TiXmlNode,相當(dāng)于調(diào)用了TiXmlNode的析構(gòu)函數(shù)。
質(zhì)疑:網(wǎng)上說(shuō)這種方式,析構(gòu)是從葉子到樹根。根據(jù)TiXmlNode中的析構(gòu)函數(shù),我們可以得出,是從樹根到葉子。
但是我們?cè)贒elete myDocument時(shí),應(yīng)該注意一點(diǎn):
創(chuàng)建文檔時(shí),也就是程序段中的myDocument。若是從堆上創(chuàng)建,則需需要手動(dòng)釋放。如我們上述的片段中,就是在堆上創(chuàng)建的。
TiXmlDocument *myDocument=new TiXmlDocument ();
若是從棧上創(chuàng)建,則不須我們手動(dòng)釋放,而是程序自動(dòng)調(diào)用析構(gòu)函數(shù)。同時(shí)我們應(yīng)該注意,其他的元素必須在堆上創(chuàng)建。因?yàn)樵赥iXmlNode析構(gòu)函數(shù)中,是delete的,但是棧上的東東是不須delete,所以除了根節(jié)點(diǎn)之外連接的后代節(jié)點(diǎn)是必須從堆上創(chuàng)建。
經(jīng)過(guò)我們解釋,明白tinyxml中的原理了嗎?只要理解了tinyxml中的類的作用以及類之間的關(guān)系,看源碼是沒(méi)問(wèn)題滴哦。
這篇博客根據(jù)創(chuàng)建xml小demo解釋了其中存在的疑問(wèn)。那下篇博客中我們會(huì)根據(jù)解析xml來(lái)答疑解析中存在的問(wèn)題。
相關(guān)文章
用C編寫一個(gè)送給女朋友的情人節(jié)小程序 可愛(ài)!
非??蓯?ài)的情人節(jié)小程序!文章為大家分享了用C編寫一個(gè)送給女朋友的小程序,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-02-02
C語(yǔ)言中的while循環(huán)語(yǔ)句示例詳解
這篇文章主要介紹了C語(yǔ)言中的while循環(huán)語(yǔ)句,主要包括while循環(huán)的基本信息及常見問(wèn)題,本文結(jié)合實(shí)例代碼給大家講解的非常詳細(xì),需要的朋友可以參考下2023-06-06
詳解C語(yǔ)言內(nèi)核字符串轉(zhuǎn)換方法
在內(nèi)核開發(fā)模式下,初始化字符串也需要調(diào)用專用的初始化函數(shù),如下分別初始化ANSI和UNCODE字符串,本文我們就來(lái)看看代碼是如何實(shí)現(xiàn)的2022-09-09
史上最強(qiáng)C語(yǔ)言分支和循環(huán)教程詳解
這篇文章主要介紹了史上最強(qiáng)C語(yǔ)言分支和循環(huán)教程詳解,本文通過(guò)代碼演示給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-11-11

