[C++]使用TinyXml讀寫Xml

 

文章標籤

  • Effective C#

more tags...

每月文章

  • 2012年9月 (3)
  • 2012年8月 (12)
  • 2012年7月 (8)
  • 2012年6月 (16)
  • 2012年5月 (9)
  • 2012年4月 (10)
  • 2012年3月 (12)
  • 2012年2月 (7)
  • 2012年1月 (5)
  • 2011年12月 (8)
  • 2011年11月 (11)
  • 2011年10月 (9)
  • 2011年9月 (13)
  • 2011年8月 (13)
  • 2011年7月 (6)
  • 2011年6月 (9)
  • 2011年5月 (11)
  • 2011年4月 (16)
  • 2011年3月 (16)
  • 2011年2月 (6)
  • 2011年1月 (10)
  • 2010年12月 (7)
  • 2010年11月 (20)
  • 2010年10月 (16)
  • 2010年9月 (2)
  • 2010年8月 (8)
  • 2010年7月 (7)
  • 2010年6月 (17)
  • 2010年5月 (9)
  • 2010年4月 (18)
  • 2010年3月 (12)
  • 2010年2月 (7)
  • 2010年1月 (17)
  • 2009年12月 (13)
  • 2009年11月 (4)
  • 2009年10月 (11)
  • 2009年9月 (16)
  • 2009年8月 (13)
  • 2009年7月 (12)
  • 2009年6月 (17)
  • 2009年5月 (22)
  • 2009年4月 (29)
  • 2009年3月 (10)
  • 2009年2月 (5)
  • 2009年1月 (5)
  • 2008年11月 (8)

文章分類

  • .NET Concept (21)
  • .NET Resource (33)
  • C# (184)
  • C++ (34)
  • Control (4)
  • Design Pattern (7)
  • Investment (5)
  • Library (4)
  • Linq (8)
  • Other (10)
  • Performance (8)
  • Security (1)
  • Software (22)
  • UML (6)
  • VB.NET (105)
  • Visual Studio (65)
  • WCF (1)
  • Web (9)
  • WF (2)
  • WLW (5)
  • WPF (13)
  • 心智筆記 (2)

實用網站

  • Dropbox免費雲端儲存服務

程式Blog

  • .NET Midway
  • .NET菜鳥自救會
  • ASP.NET 魔法學院
  • Huan-Lin 學習筆記
  • MIS2000 Lab
  • topcat姍舞之間的極度凝聚
  • VB/ VBA/ C#/ Java/ C++ 語言學習筆記
  • 小朱® 的技術隨手寫
  • 強力鎯頭 VB BLOG
  • 瓶水相逢.Net
  • 黑暗執行緒

程式碼範例

  • Code Project

程式討論區

  • 微軟技術社群
  • 程式設計俱樂部

最新回應

  • re: [C#]取用.picasa.ini內存的現有資訊來做臉部偵測真的是高手...by demo
  • re: [C#]阿拉伯數字轉國字土法鍊鋼又是隨手寫的小範例 難免會有些問題 你說的問題應該是不太像我們常用的那樣顯示....by 蹂躪
  • re: [C#]阿拉伯數字轉國字打上 7654321 就錯了by Jerry
  • re: [Software]ScreenSnapr能幫你上傳圖片的螢幕抓圖工具嗚嗚,一直連不到官網?by 小黑
  • re: [C#]取用.picasa.ini內存的現有資訊來做臉部偵測高手by 當麻許
  • re: [C#]使用Microsoft Translator Soap API實作翻譯功能可以直接调用微软的http直接翻译.自己的API有字量限制.by xiebbs
  • re: DotNetZip使用切割壓縮檔,超過4G的檔案,每個切600MB似乎會出錯。 bad read of ent....by 阿徵
  • re: [C#][VB.NET]使用AxMediaPlayer撥放多媒體to meteorli : 你可以用程式控制看看是否能快轉 如果不行~代表影片可能....by 蹂躪
  • re: [C#][VB.NET]使用AxMediaPlayer撥放多媒體您好 圖片中紅圈的部份無法點選,我有抓下您提供的範例。這些灰色部分鼠標指上去顯示:....by meteorli
  • re: [C#][VB.NET]使用AxMediaPlayer撥放多媒體to meteorli : 這種特殊功能一定是要自己做的,灰色的部分這樣聽是不知道怎麼回事,你可以看....by 蹂躪
<< [C++]使用Pageheap偵測記憶體越界錯誤  Home  [C#][WPF]WPF程式接收視窗訊息 >>

[C++]使用TinyXml讀寫Xml

     
 

在C++讀寫XML並不像在.NET一般容易,常看到的方法若不是自己解析,就是用MSXml或是TinyXml下去處理,這邊簡單的紀錄一下TinyXml的用法。

 

自網站下載完TinyXml後解壓縮後,我們可以看到裡面會有tinystr.cpp、tinystr.h、tinyxml.cpp、tinyxml.h、tinyxmlerror.cpp、與tinyxmlparser.cpp這六個檔案,TinyXml主要就是用這六個檔案。

 

將這六個檔案加入專案中,並在cpp檔前加入#include "stdafx",將Precompile header加入 。

 

在要使用到TinyXml的地方加入tinyxml.h與tinystr.h兩個必要的標頭檔,就可以開始使用了。

1 #include "tinyxml.h"  
2 #include "tinystr.h"

 

TinyXml內含TiXmlBase、TiXmlNode、TiXmlDocument、TiXmlElement、TiXmlComment、TiXmlDeclaration、TiXmlText、TiXmlUnknown、TiXmlAttribute這幾個重要的類別,從命名就可以大致了解他們的用途,像是TiXmlDocument表示Xml文件、TiXmlElement是Xml元素節點、TiXmlComment是Xml中的註解、TiXmlAttribute是Xml節點的屬性。

 

在寫入Xml時,首先必須建立TiXmlDocument,為其加入TiXmlElement、TiXmlText與其它的Xml節點元素,再叫用SaveFile方法帶入Xml檔案位置就可以了。

01 void SaveXml(Person* person, string file)
02 {  
03     TiXmlDocument xmlDoc;
04  
05     TiXmlNode* rootElement = xmlDoc.InsertEndChild(TiXmlElement("Person"));
06  
07     rootElement
08         ->InsertEndChild(TiXmlElement("Name"))
09         ->InsertEndChild(TiXmlText(person->m_sName.c_str()));
10  
11     rootElement
12         ->InsertEndChild(TiXmlElement("NickName"))
13         ->InsertEndChild(TiXmlText(person->m_sNickName.c_str()));
14  
15     char buffer[256];
16     _itoa(person->m_nAge, buffer,10);
17     rootElement
18         ->InsertEndChild(TiXmlElement("Age"))
19         ->InsertEndChild(TiXmlText(buffer));
20  
21     xmlDoc.SaveFile(file.c_str());
22 }

 

讀取Xml時,一樣是要先建立TiXmlDocument物件,在建構時帶入Xml檔案位置,再叫用LoadFile將檔案讀入。讀入Xml後若讀取有問題,我們可叫用ErrorId判斷是否有錯誤發生,若取得的ErrorId大於0,可再叫用ErrorDesc去判斷發生的錯誤是甚麼。若Xml讀取沒問題的話可接著解析Xml的內容,透過RootElement可取得Xml的根節點,FirstChildElement可取得Xml子節點,NextSibling可用來取得Xml的兄弟節點,取得了Xml節點後透過GetText方法就可以得到Xml節點的內容。像是下面這樣:

01 void LoadXml(string file, Person* person)
02 {  
03     TiXmlDocument xmlDoc(file.c_str());
04  
05     xmlDoc.LoadFile();
06  
07     if(xmlDoc.ErrorId() > 0)
08         return;
09  
10     TiXmlElement* pRootElement = xmlDoc.RootElement();
11  
12     if(!pRootElement)
13         return;
14  
15     TiXmlElement* pNode = NULL;
16      
17     pNode = pRootElement->FirstChildElement("Name");
18     if(pNode)
19     {
20         person->m_sName = pNode->GetText();      
21     }
22  
23     pNode = pRootElement->FirstChildElement("NickName");
24     if(pNode)
25     {
26         person->m_sNickName = pNode->GetText();      
27     }
28  
29     pNode = pRootElement->FirstChildElement("Age");
30     if(pNode)
31     {
32         person->m_nAge = atoi(pNode->GetText());     
33     }
34 }

 

完整的程式範例如下:

01 // ConsoleApplication11.cpp : Defines the entry point for the console application.
02 //
03  
04 #include "stdafx.h"
05 #include <string>
06 #include "tinyxml.h"  
07 #include "tinystr.h"
08  
09 using namespace std;
10  
11 class Person
12 {
13 public:
14     string  m_sName;
15     string  m_sNickName;
16     int     m_nAge;
17 };
18  
19 void SaveXml(Person* person, string file)
20 {  
21     TiXmlDocument xmlDoc;
22  
23     TiXmlNode* rootElement = xmlDoc.InsertEndChild(TiXmlElement("Person"));
24  
25     rootElement
26         ->InsertEndChild(TiXmlElement("Name"))
27         ->InsertEndChild(TiXmlText(person->m_sName.c_str()));
28  
29     rootElement
30         ->InsertEndChild(TiXmlElement("NickName"))
31         ->InsertEndChild(TiXmlText(person->m_sNickName.c_str()));
32  
33     char buffer[256];
34     _itoa(person->m_nAge, buffer,10);
35     rootElement
36         ->InsertEndChild(TiXmlElement("Age"))
37         ->InsertEndChild(TiXmlText(buffer));
38  
39     xmlDoc.SaveFile(file.c_str());
40 }
41  
42 void LoadXml(string file, Person* person)
43 {  
44     TiXmlDocument xmlDoc(file.c_str());
45  
46     xmlDoc.LoadFile();
47  
48     if(xmlDoc.ErrorId() > 0)
49         return;
50  
51     TiXmlElement* pRootElement = xmlDoc.RootElement();
52  
53     if(!pRootElement)
54         return;
55  
56     TiXmlElement* pNode = NULL;
57      
58     pNode = pRootElement->FirstChildElement("Name");
59     if(pNode)
60     {
61         person->m_sName = pNode->GetText();      
62     }
63  
64     pNode = pRootElement->FirstChildElement("NickName");
65     if(pNode)
66     {
67         person->m_sNickName = pNode->GetText();      
68     }
69  
70     pNode = pRootElement->FirstChildElement("Age");
71     if(pNode)
72     {
73         person->m_nAge = atoi(pNode->GetText());     
74     }
75 }
76  
77 int _tmain(int argc, _TCHAR* argv[])
78 {
79     string file = "Person.xml";
80  
81     Person Larry;
82     Larry.m_sName       = "Larry";
83     Larry.m_sNickName   = "蹂躪";
84     Larry.m_nAge        = 30;
85      
86     SaveXml(&Larry, file);
87  
88  
89     Person NewLarry;
90  
91     LoadXml(file, &NewLarry);
92  
93     printf("Name: %s\r\n", NewLarry.m_sName.c_str());
94     printf("NickName: %s\r\n", NewLarry.m_sNickName.c_str());
95     printf("Age: %d\r\n", NewLarry.m_nAge);
96  
97     return 0;
98 }

 

範例運行後會產生個Xml,內容像下面這般:

 

Xml的資料也能正常的解析。

 

TinyXml使用上算是比較不複雜的,但是卻有個很麻煩的問題,就是轉碼的動作必須自己處理,若不經轉換可能會有亂碼的問題,網路上有些文章就是專門在討論這樣的問題。另外,它的Xml存檔格式是用ANSI的格是下去儲存,若是要以UTF-8去儲存,必須修改tinyxml的程式碼,直接搜尋程式找到useMicrosoftBOM,將這值設為true就可以了。

 

這邊筆者為了方便使用,有將TinyXml包成類似.NET的XmlWriter類別,存取Xml的部分就會變得像下面這樣:

01 void SaveXml(Person* person, string file)
02 {
03     XmlWriter xw(file);
04  
05     xw
06         .WriteStartElement("Person")
07             .WriteElementValue("Name", person->m_sName)
08             .WriteElementValue("NickName", person->m_sNickName)
09             .WriteElementValue("Age", person->m_nAge)
10         .WriteEndElement()
11         .Close();
12 }

 

程式碼分享於下方,有需要的自行取用。

XmlWriter.h

001 #pragma once
002 #include <stack>
003 #include <string>
004 #include "tinyxml.h"  
005 #include "tinystr.h"
006  
007 using namespace std;
008 class XmlWriter
009 {
010 #pragma region Const
011 private:
012 #define DEFAULT_BUFFER_SIZE 512
013 #pragma endregion
014  
015  
016 #pragma region Var
017 private:
018     char                m_cBuffer[DEFAULT_BUFFER_SIZE];
019     string              _sFile;
020     TiXmlDocument       _XmlDoc;   
021     stack<TiXmlNode*> _StartNodes;
022 #pragma endregion
023  
024  
025 #pragma region Private Property
026 private:
027     __declspec(property(get=Get_sFile,put=Set_sFile))
028         string m_sFile;
029  
030     __declspec(property(get=Get_XmlDoc,put=Set_XmlDoc))
031         TiXmlDocument& m_XmlDoc;
032  
033     __declspec(property(get=Get_StartNodes))
034         stack<TiXmlNode*>& m_StartNodes;
035  
036     __declspec(property(get=Get_pCurrentNode,put=Set_pCurrentNode))

你可能感兴趣的:([C++]使用TinyXml讀寫Xml)