文章數(515) 回應數(573) 引用數(0)
Level Up
謙卑學習,持之以恆,才能不斷的Level Up
每月文章
- 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)
文章分類
實用網站
程式Blog
程式碼範例
最新回應
- 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++讀寫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)) |
037 | TiXmlNode* m_pCurrentNode; |
038 | #pragma endregion |
039 |
040 |
041 | #pragma region Constructor & DeConstructor |
042 | public : |
043 | XmlWriter(string file); |
044 | ~XmlWriter( void ); |
045 | #pragma endregion |
046 |
047 |
048 | #pragma region Property Process Method |
049 | private : |
050 | inline string Get_sFile() |
051 | { |
052 | return _sFile; |
053 | } |
054 |
055 | inline void Set_sFile(string value) |
056 | { |
057 | if (_sFile == value) |
058 | return ; |
059 |
060 | _sFile = value; |
061 | } |
062 |
063 | inline TiXmlDocument& Get_XmlDoc() |
064 | { |
065 | return _XmlDoc; |
066 | } |
067 |
068 | inline void Set_XmlDoc(TiXmlDocument& value) |
069 | { |
070 | _XmlDoc = value; |
071 | } |
072 |
073 | inline TiXmlNode* Get_pCurrentNode() |
074 | { |
075 | if (m_StartNodes.empty()) |
076 | { |
077 | return &m_XmlDoc; |
078 | } |
079 | return m_StartNodes.top(); |
080 | } |
081 |
082 | inline stack<TiXmlNode*>& Get_StartNodes() |
083 | { |
084 | return _StartNodes; |
085 | } |
086 | #pragma endregion |
087 |
088 |
089 | #pragma region Protected Method |
090 | protected : |
091 | void Reset(); |
092 | #pragma endregion |
093 |
094 |
095 | #pragma region Public Method |
096 | public : |
097 | XmlWriter& WriteStartElement(string localName); |
098 | XmlWriter& WriteEndElement(); |
099 | XmlWriter& WriteElementValue(string localName, const char * value); |
100 | XmlWriter& WriteElementValue(string localName, string value); |
101 | XmlWriter& WriteElementValue(string localName, int value); |
102 | void Close(); |
103 | #pragma endregion |
104 | }; |
XmlWriter.cpp
01 | #include "stdafx.h" |
02 | #include "XmlWriter.h" |
03 |
04 | #pragma region Constructor & DeConstructor |
05 | XmlWriter::XmlWriter(string file) |
06 | { |
07 | Reset(); |
08 | m_sFile = file; |
09 | } |
10 |
11 |
12 | XmlWriter::~XmlWriter( void ) |
13 | { |
14 | Reset(); |
15 | } |
16 | #pragma endregion |
17 |
18 |
19 |
20 | #pragma region Protected Method |
21 | void XmlWriter::Reset() |
22 | { |
23 | _sFile = "" ; |
24 | _XmlDoc.Clear(); |
25 | } |
26 | #pragma endregion |
27 |
28 |
29 | #pragma region Public Method |
30 | XmlWriter& XmlWriter::WriteStartElement(string localName) |
31 | { |
32 | m_StartNodes.push(m_pCurrentNode->InsertEndChild(TiXmlElement(localName.c_str()))); |
33 |
34 | return * this ; |
35 | } |
36 |
37 | XmlWriter& XmlWriter::WriteEndElement() |
38 | { |
39 | if (!m_StartNodes.empty()) |
40 | m_StartNodes.pop(); |
41 |
42 | return * this ; |
43 | } |
44 |
45 | XmlWriter& XmlWriter::WriteElementValue(string localName, const char * value) |
46 | { |
47 | m_pCurrentNode |
48 | ->InsertEndChild(TiXmlElement(localName.c_str())) |
49 | ->InsertEndChild(TiXmlText(value)); |
50 |
51 | return * this ; |
52 | } |
53 |
54 | XmlWriter& XmlWriter::WriteElementValue(string localName, string value) |
55 | { |
56 | return WriteElementValue(localName, value.c_str()); |
57 | } |
58 |
59 | XmlWriter& XmlWriter::WriteElementValue(string localName, int value) |
60 | { |
61 | _itoa(value, m_cBuffer,10); |
62 | return WriteElementValue(localName, m_cBuffer); |
63 | } |
64 |
65 | void XmlWriter::Close() |
66 | { |
67 | m_XmlDoc.SaveFile(m_sFile.c_str()); |
68 | Reset(); |
69 | } |
70 | #pragma endregion |
Link
- TinyXml Main Page
- TinyXml Documentation
- TinyXml Project Page
- TinyXML - 小巧好用的 XML parser
- TinyXML Tutorial 中文指南