注: 本文是 TinyXML 2.5.3 版本 Document 中的《TinyXML Tutorial》的翻譯文檔,由本人 Dennis.Gao 翻譯,版權歸原作者所有,轉載本文檔請註明出處。原文出自 TinyXML 源碼包doc目錄。在線文檔:http://www.grinninglizard.com/tinyxmldocs/tutorial0.html
Author : Dennis.Gao
Date : 2008.01.01
這是什麼?
本指南就如何有效的使用 TinyXML 提供一些竅門和建議。
這裏也會包括一些 C++ 的竅門,像如何在字符串和整數之間進行轉換。這和 TinyXML 本身並沒有任何關係,但是它會對你的工程有所幫助,所以我把它寫了進來。
如果你不知道 C++ 的基本概念,那麼本指南對你沒有任何用處。同樣,如果你不知道 DOM 是什麼,先在別的地方學習一下吧。
開始之前
一些 XML 數據集/文件將會被用到:
<
?
xml version
=
"1.0"
?>
<
Hello>
World<
/
Hello>
|
example2.xml:
<
?
xml version
=
"1.0"
?>
<
poetry>
<
verse>
Alas
Great
World
Alas (
again)
<
/
verse>
<
/
poetry>
|
example3.xml:
<
?
xml version
=
"1.0"
?>
<
shapes>
<
circle name=
"int-based"
x=
"20"
y=
"30"
r=
"50"
/
>
<
point
name=
"float-based"
x=
"3.5"
y=
"52.1"
/
>
<
/
shapes>
|
example4.xml:
<
?
xml version
=
"1.0"
?>
<
MyApp>
<
!-- Settings for MyApp -->
<
Messages>
<
Welcome>
Welcome to MyApp<
/
Welcome>
<
Farewell>
Thank you for using MyApp<
/
Farewell>
<
/
Messages>
<
Windows>
<
Window name=
"MainFrame"
x=
"5"
y=
"15"
w=
"400"
h=
"250"
/
>
<
/
Windows>
<
Connection ip=
"192.168.0.1"
timeout=
"123.456000"
/
>
<
/
MyApp>
|
開始起
步
從文件加載
XML
將一個文件加載到 TinyXML DOM 中的最簡單方法:
TiXmlDocument doc(
"demo.xml"
)
;
doc.
LoadFile(
)
;
|
下面是一個更實際的用法。它會加載文件並在標準輸出中顯示文件內容:
// load the named
file and dump its structure to STDOUT
void
dump_to_stdout(
const
char
*
pFilename)
{
TiXmlDocument doc(
pFilename)
;
bool
loadOkay =
doc.
LoadFile(
)
;
if
(
loadOkay)
{
printf
(
"/n%s:/n"
,
pFilename)
;
dump_to_stdout(
&
doc )
;
// defined later in the tutorial
}
else
{
printf
(
"Failed to load file /"%s/"/n"
,
pFilename)
;
}
}
|
這是在 main() 函數中使用這個函數的簡單示例:
int
main(
void
)
{
dump_to_stdout(
"example1.xml"
)
;
return
0;
}
|
Example 1
的 XML
是:
<
?
xml version
=
"1.0"
?>
<
Hello>
World<
/
Hello>
|
運行這個程序就可以將 XML 文件顯示在控制檯或 DOS 窗口中:
DOCUMENT +
DECLARATION +
ELEMENT
Hello
+
TEXT[
World]
|
在本指南的後面會給出 dump_to_stdout() 函數的定義,它對你瞭解如何遞歸遍歷一個 DOM 十分有用。
通過編程建立 XML 文檔
下面的函數可以建立 Example 1 文檔:
void
build_simple_doc(
)
{
//
Make xml: <?xml ..><Hello>World</Hello>
TiXmlDocument
doc;
TiXmlDeclaration
*
decl =
new
TiXmlDeclaration(
"1.0"
,
""
,
""
)
;
TiXmlElement *
element =
new
TiXmlElement(
"Hello"
)
;
TiXmlText
*
text =
new
TiXmlText(
"World"
)
;
element-
>
LinkEndChild(
text )
;
doc.
LinkEndChild(
decl )
;
doc.
LinkEndChild(
element )
;
doc.
SaveFile(
"madeByHand.xml"
)
;
}
|
可以通過下面的調用來加載文件並將它顯示在控制檯上:
dump_to_stdout(
"madeByHand.xml"
)
;
// this func defined later in the tutorial
|
你會發現它和 Example 1 是完全一樣的:
madeByHand.
xml:
Document +
Declaration +
Element [
Hello]
+
Text: [
World]
|
下面這段代碼通過節點的建立和連接的不同順序生成一個完全相同的 XML DOM :
void
write_simple_doc2(
)
{
//
same as write_simple_doc1 but add each node
// as early as possible into the tree.
TiXmlDocument
doc;
TiXmlDeclaration
*
decl =
new
TiXmlDeclaration(
"1.0"
,
""
,
""
)
;
doc.
LinkEndChild(
decl )
;
TiXmlElement
*
element =
new
TiXmlElement(
"Hello"
)
;
doc.
LinkEndChild(
element )
;
TiXmlText
*
text =
new
TiXmlText(
"World"
)
;
element-
>
LinkEndChild(
text )
;
doc.
SaveFile(
"madeByHand2.xml"
)
;
}
|
這兩段代碼生成的是同一段 XML ,如下:
<
?
xml version
=
"1.0"
?>
<
Hello>
World<
/
Hello>
|
也就是這種結構形式:
DOCUMENT +
DECLARATION +
ELEMENT
Hello
+
TEXT[
World]
|
屬性
很簡單就可以給一個已經存在的節點設置屬性:
window =
new
TiXmlElement(
"Demo"
)
;
window-
>
SetAttribute(
"name"
,
"Circle"
)
;
window-
>
SetAttribute(
"x"
,
5)
;
window-
>
SetAttribute(
"y"
,
15)
;
window-
>
SetDoubleAttribute(
"radius"
,
3.
14159)
;
|
你也可以使用 TiXmlAttribute 對象來做這件事。
下面這段代碼給出了一種(並非僅此一種)如何得到一個元素的所有屬性,然後打印出名字和字符串值的方法,並且,如果這些值可以轉換成整形或浮點型,那麼把他們也打印出來:
// print all
attributes of pElement.
// returns the number of attributes printed
int
dump_attribs_to_stdout(
TiXmlElement*
pElement,
unsigned
int
indent)
{
if
(
!
pElement )
return
0;
TiXmlAttribute*
pAttrib=
pElement-
>
FirstAttribute(
)
;
int
i=
0;
int
ival;
double
dval;
const
char
*
pIndent=
getIndent(
indent)
;
printf
(
"/n"
)
;
while
(
pAttrib)
{
printf
(
"%s%s:
value=[%s]"
,
pIndent,
pAttrib-
>
Name(
)
,
pAttrib-
>
Value(
)
)
;
if
(
pAttrib-
>
QueryIntValue(
&
ival)
=
=
TIXML_SUCCESS)
printf
(
"
int=%d"
,
ival)
;
if
(
pAttrib-
>
QueryDoubleValue(
&
dval)
=
=
TIXML_SUCCESS)
printf
(
"
d=%1.1f"
,
dval)
;
printf
(
"/n"
)
;
i+
+
;
pAttrib=
pAttrib-
>
Next(
)
;
}
return
i;
}
|
將文檔寫入文件
將建立好的 DOM
寫入一個文件很簡單:
doc.
SaveFile(
saveFilename )
;
|
回想一下 example 4:
<
?
xml version
=
"1.0"
?>
<
MyApp>
<
!-- Settings for MyApp -->
<
Messages>
<
Welcome>
Welcome to MyApp<
/
Welcome>
<
Farewell>
Thank you for using MyApp<
/
Farewell>
<
/
Messages>
<
Windows>
<
Window name=
"MainFrame"
x=
"5"
y=
"15"
w=
"400"
h=
"250"
/
>
<
/
Windows>
<
Connection ip=
"192.168.0.1"
timeout=
"123.456000"
/
>
<
/
MyApp>
|
下面的函數用來建立這個 DOM 並把它寫進一份名爲 "appsettings.xml" 的文件中:
void
write_app_settings_doc(
)
{
TiXmlDocument doc;
TiXmlElement*
msg;
TiXmlDeclaration*
decl =
new
TiXmlDeclaration(
"1.0"
,
""
,
""
)
;
doc.
LinkEndChild(
decl )
;
TiXmlElement *
root =
new
TiXmlElement(
"MyApp"
)
;
doc.
LinkEndChild(
root )
;
TiXmlComment *
comment =
new
TiXmlComment(
)
;
comment-
>
SetValue(
"
Settings for MyApp "
)
;
root-
>
LinkEndChild(
comment )
;
TiXmlElement *
msgs =
new
TiXmlElement(
"Messages"
)
;
root-
>
LinkEndChild(
msgs )
;
msg =
new
TiXmlElement(
"Welcome"
)
;
msg-
>
LinkEndChild(
new
TiXmlText(
"Welcome to MyApp"
)
)
;
msgs-
>
LinkEndChild(
msg )
;
msg
=
new
TiXmlElement(
"Farewell"
)
;
msg-
>
LinkEndChild(
new
TiXmlText(
"Thank you for using MyApp"
)
)
;
msgs-
>
LinkEndChild(
msg )
;
TiXmlElement *
windows =
new
TiXmlElement(
"Windows"
)
;
root-
>
LinkEndChild(
windows )
;
TiXmlElement *
window;
window =
new
TiXmlElement(
"Window"
)
;
windows-
>
LinkEndChild(
window )
;
window-
>
SetAttribute(
"name"
,
"MainFrame"
)
;
window-
>
SetAttribute(
"x"
,
5)
;
window-
>
SetAttribute(
"y"
,
15)
;
window-
>
SetAttribute(
"w"
,
400)
;
window-
>
SetAttribute(
"h"
,
250)
;
TiXmlElement *
cxn =
new
TiXmlElement(
"Connection"
)
;
root-
>
LinkEndChild(
cxn )
;
cxn-
>
SetAttribute(
"ip"
,
"192.168.0.1"
)
;
cxn-
>
SetDoubleAttribute(
"timeout"
,
123.
456)
;
// floating point
attrib
dump_to_stdout(
&
doc )
;
doc.
SaveFile(
"appsettings.xml"
)
;
}
|
通過 dump_to_stdout() 函數可以顯示這個結構:
Document +
Declaration +
Element [
MyApp]
(
No
attributes)
+
Comment: [
Settings for MyApp ]
+
Element [
Messages]
(
No attributes)
+
Element [
Welcome]
(
No attributes)
+
Text: [
Welcome to MyApp]
+
Element [
Farewell]
(
No attributes)
+
Text: [
Thank you for using MyApp]
+
Element [
Windows]
(
No attributes)
+
Element [
Window]
+
name: value=
[
MainFrame]
+
x: value=
[
5]
int=
5 d=
5.
0
+
y: value=
[
15]
int=
15 d=
15.
0
+
w: value=
[
400]
int=
400 d=
400.
0
+
h: value=
[
250]
int=
250 d=
250.
0
5 attributes
+
Element [
Connection]
+
ip: value=
[
192.
168.
0.
1]
int=
192 d=
192.
2
+
timeout: value=
[
123.
456000]
int=
123 d=
123.
5
2
attributes
|
很高興在默認的情況下, TinyXml 用其他的 API 所謂的“優美”格式來寫 XML ,它修改元素文字的空白,然後用嵌套層次的方式顯示這棵樹。
我沒有注意到在寫文件的時候是否有辦法關掉縮排,但是這肯定很容易。
[ Lee:在 STL 模式下很容易,只要使用 cout << myDoc 就可以了。非 STL 模式通常是“優美”格式的。加入一個“開關”會是一個不錯的特性,並且已經這麼做了。]
XML 與 C++ 對象之間的轉換
介紹
這個示例假定你正要加載你的應用設置並把它們保存在 XML 文件中,就像 example4.xml 那樣。
有許多辦法可以完成這件事。例如,看一看 TinyBind 這個工程,你可以在這裏找到它:
http://sourceforge.net/projects/tinybind
本節給出一個使用 XML 來加載並保存一個基本的對象結構的淺顯易懂的方法。
建立你的對象類
先從下面的這些基類入手:
#
include
<
string
>
#
include
<
map
>
using
namespace
std
;
typedef
std
:
:
map
<
std
:
:
string
,
std
:
:
string
>
MessageMap;
// a basic window abstraction - demo
purposes only
class
WindowSettings {
public
:
int
x,
y,
w,
h;
string
name;
WindowSettings(
)
:
x(
0)
,
y(
0)
,
w(
100)
,
h(
100)
,
name(
"Untitled"
)
{
}
WindowSettings(
int
x,
int
y,
int
w,
int
h,
const
string
&
name)
{
this
-
>
x=
x;
this
-
>
y=
y;
this
-
>
w=
w;
this
-
>
h=
h;
this
-
>
name=
name;
}
}
;
class
ConnectionSettings {
public
:
string
ip;
double
timeout;
}
;
class
AppSettings {
public
:
string
m_name;
MessageMap m_messages;
list
<
WindowSettings>
m_windows;
ConnectionSettings m_connection;
AppSettings(
)
{
}
void
save(
const
char
*
pFilename)
;
void
load(
const
char
*
pFilename)
;
// just to show how to do it
void
setDemoValues(
)
{
m_name=
"MyApp"
;
m_messages.
clear(
)
;
m_messages[
"Welcome"
]
=
"Welcome to "
+
m_name;
m_messages[
"Farewell"
]
=
"Thank you for using "
+
m_name;
m_windows.
clear(
)
;
m_windows.
push_back(
WindowSettings(
15,
15,
400,
250,
"Main"
)
)
;
m_connection.
ip=
"Unknown"
;
m_connection.
timeout=
123.
456;
}
}
;
|
這是一個簡化的 main() 函數,它演示瞭如何建立一個默認設置的樹的對象,保存它以及重新載入它:
int
main(
void
)
{
AppSettings settings;
settings.
save(
"appsettings2.xml"
)
;
settings.
load(
"appsettings2.xml"
)
;
return
0;
}
|
下面這個 main() 函數演示瞭如何建立,修改,保存,還有加載一個結構體:
int
main(
void
)
{
// block: customise and save settings
{
AppSettings
settings;
settings.
m_name=
"HitchHikerApp"
;
settings.
m_messages[
"Welcome"
]
=
"Don't Panic"
;
settings.
m_messages[
"Farewell"
]
=
"Thanks for all
the fish"
;
settings.
m_windows.
push_back(
WindowSettings(
15,
25,
300,
250,
"BookFrame"
)
)
;
settings.
m_connection.
ip=
"192.168.0.77"
;
settings.
m_connection.
timeout=
42.
0;
settings.
save(
"appsettings2.xml"
)
;
}
// block: load settings
{
AppSettings
settings;
settings.
load(
"appsettings2.xml"
)
;
printf
(
"%s: %s/n"
,
settings.
m_name.
c_str(
)
,
settings.
m_messages[
"Welcome"
]
.
c_str(
)
)
;
WindowSettings
&
w=
settings.
m_windows.
front(
)
;
printf
(
"%s: Show
window '%s' at %d,%d (%d x %d)/n"
,
settings.
m_name.
c_str(
)
,
w.
name.
c_str(
)
,
w.
x,
w.
y,
w.
w,
w.
h)
;
printf
(
"%s: %s/n"
,
settings.
m_name.
c_str(
)
,
settings.
m_messages[
"Farewell"
]
.
c_str(
)
)
;
}
return
0;
}
|
當 save() 函數和 load() 函數完成後(在下面),運行這個 main() 函數,在控制檯會顯示:
HitchHikerApp: Don't Panic
HitchHikerApp: Show window
'BookFrame' at 15,25 (300 x 100)
HitchHikerApp: Thanks for all
the fish
|
編碼爲 XML
有許多不同的方法來解決如何將它(一個結構體)保存在文件中。比如:
void
AppSettings:
:
save(
const
char
*
pFilename)
{
TiXmlDocument doc;
TiXmlElement*
msg;
TiXmlComment *
comment;
string
s;
TiXmlDeclaration*
decl =
new
TiXmlDeclaration(
"1.0"
,
""
,
""
)
;
doc.
LinkEndChild(
decl )
;
TiXmlElement
*
root =
new
TiXmlElement(
m_name.
c_str(
)
)
;
doc.
LinkEndChild(
root )
;
comment
=
new
TiXmlComment(
)
;
s=
"
Settings for "
+
m_name+
" "
;
comment-
>
SetValue(
s.
c_str(
)
)
;
root-
>
LinkEndChild(
comment )
;
// block: messages
{
MessageMap:
:
iterator
iter;
TiXmlElement
*
msgs =
new
TiXmlElement(
"Messages"
)
;
root-
>
LinkEndChild(
msgs )
;
for
(
iter=
m_messages.
begin(
)
;
iter !
=
m_messages.
end(
)
;
iter+
+
)
{
const
string
&
key=
(
*
iter)
.
first;
const
string
&
value=
(
*
iter)
.
second;
msg
=
new
TiXmlElement(
key.
c_str(
)
)
;
msg-
>
LinkEndChild(
new
TiXmlText(
value.
c_str(
)
)
)
;
msgs-
>
LinkEndChild(
msg )
;
}
}
// block: windows
{
TiXmlElement *
windowsNode =
new
TiXmlElement(
"Windows"
)
;
root-
>
LinkEndChild(
windowsNode )
;
list
<
WindowSettings>
:
:
iterator
iter;
for
(
iter=
m_windows.
begin(
)
;
iter !
=
m_windows.
end(
)
;
iter+
+
)
{
const
WindowSettings&
w=
*
iter;
TiXmlElement
*
window;
window =
new
TiXmlElement(
"Window"
)
;
windowsNode-
>
LinkEndChild(
window )
;
window-
>
SetAttribute(
"name"
,
w.
name.
c_str(
)
)
;
window-
>
SetAttribute(
"x"
,
w.
x)
;
window-
>
SetAttribute(
"y"
,
w.
y)
;
window-
>
SetAttribute(
"w"
,
w.
w)
;
window-
>
SetAttribute(
"h"
,
w.
h)
;
}
}
// block: connection
{
TiXmlElement *
cxn =
new
TiXmlElement(
"Connection"
)
;
root-
>
LinkEndChild(
cxn )
;
cxn-
>
SetAttribute(
"ip"
,
m_connection.
ip.
c_str(
)
)
;
cxn-
>
SetDoubleAttribute(
"timeout"
,
m_connection.
timeout)
;
}
doc.
SaveFile(
pFilename)
;
}
|
運行這個修改過的 main() 函數會生成如下的文件:
<
?
xml version
=
"1.0"
?>
<
HitchHikerApp>
<
!-- Settings for HitchHikerApp -->
<
Messages>
<
Farewell>
Thanks for all the fish<
/
Farewell>
<
Welcome>
Don&
apos;
t Panic<
/
Welcome>
<
/
Messages>
<
Windows>
<
Window name=
"BookFrame"
x=
"15"
y=
"25"
w=
"300"
h=
"250"
/
>
<
/
Windows>
<
Connection ip=
"192.168.0.77"
timeout=
"42.000000"
/
>
<
/
HitchHikerApp>
|
從 XML 解碼
就像給一個對象編碼一樣,也有許多辦法可以把 XML 解碼爲你自己的 C++ 對象結構。下面的方法使用了 TiXmlHandles 類。
void
AppSettings:
:
load(
const
char
*
pFilename)
{
TiXmlDocument doc(
pFilename)
;
if
(
!
doc.
LoadFile(
)
)
return
;
TiXmlHandle
hDoc(
&
doc)
;
TiXmlElement*
pElem;
TiXmlHandle hRoot(
0)
;
// block: name
{
pElem=
hDoc.
FirstChildElement(
)
.
Element(
)
;
// should always have a valid root but
handle gracefully if it does
if
(
!
pElem)
return
;
m_name=
pElem-
>
Value(
)
;
// save this for later
hRoot=
TiXmlHandle(
pElem)
;
}
// block: string table
{
m_messages.
clear(
)
;
// trash existing
table
pElem=
hRoot.
FirstChild(
"Messages"
)
.
FirstChild(
)
.
Element(
)
;
for
(
pElem;
pElem;
pElem=
pElem-
>
NextSiblingElement(
)
)
{
const
char
*
pKey=
pElem-
>
Value(
)
;
const
char
*
pText=
pElem-
>
GetText(
)
;
if
(
pKey &
&
pText)
{
m_messages[
pKey]
=
pText;
}
}
}
// block: windows
{
m_windows.
clear(
)
;
// trash existing list
TiXmlElement*
pWindowNode=
hRoot.
FirstChild(
"Windows"
)
.
FirstChild(
)
.
Element(
)
;
for
(
pWindowNode;
pWindowNode;
pWindowNode=
pWindowNode-
>
NextSiblingElement(
)
)
{
WindowSettings w;
const
char
*
pName=
pWindowNode-
>
Attribute(
"name"
)
;
if
(
pName)
w.
name=
pName;
pWindowNode-
>
QueryIntAttribute(
"x"
,
&
w.
x)
;
// If this fails, original value is
left as-is
pWindowNode-
>
QueryIntAttribute(
"y"
,
&
w.
y)
;
pWindowNode-
>
QueryIntAttribute(
"w"
,
&
w.
w)
;
pWindowNode-
>
QueryIntAttribute(
"hh"
,
&
w.
h)
;
m_windows.
push_back(
w)
;
}
}
// block: connection
{
pElem=
hRoot.
FirstChild(
"Connection"
)
.
Element(
)
;
if
(
pElem)
{
m_connection.
ip=
pElem-
>
Attribute(
"ip"
)
;
pElem-
>
QueryDoubleAttribute(
"timeout"
,
&
m_connection.
timeout)
;
}
}
}
|
dump_to_stdout() 函數的完整代碼
下面是一份複製粘貼過來的演示程序:加載任意一份 XML 文件,然後使用上面所說的遞歸遍歷的方式將 XML 結構輸出到標準輸出中。
// tutorial demo
program
#
include
"stdafx.h"
#
include
"tinyxml.h"
//
----------------------------------------------------------------------
// STDOUT dump and indenting utility
functions
//
----------------------------------------------------------------------
const
unsigned
int
NUM_INDENTS_PER_SPACE=
2;
const
char
*
getIndent(
unsigned
int
numIndents )
{
static
const
char
*
pINDENT=
" + "
;
static
const
unsigned
int
LENGTH=
strlen
(
pINDENT )
;
unsigned
int
n=
numIndents*
NUM_INDENTS_PER_SPACE;
if
(
n >
LENGTH )
n =
LENGTH;
return
&
pINDENT[
LENGTH-
n ]
;
}
// same as getIndent but no "+" at the
end
const
char
*
getIndentAlt(
unsigned
int
numIndents )
{
static
const
char
*
pINDENT=
" "
;
static
const
unsigned
int
LENGTH=
strlen
(
pINDENT )
;
unsigned
int
n=
numIndents*
NUM_INDENTS_PER_SPACE;
if
(
n >
LENGTH )
n =
LENGTH;
return
&
pINDENT[
LENGTH-
n ]
;
}
int
dump_attribs_to_stdout(
TiXmlElement*
pElement,
unsigned
int
indent)
{
if
(
!
pElement )
return
0;
TiXmlAttribute*
pAttrib=
pElement-
>
FirstAttribute(
)
;
int
i=
0;
int
ival;
double
dval;
const
char
*
pIndent=
getIndent(
indent)
;
printf
(
"/n"
)
;
while
(
pAttrib)
{
printf
(
"%s%s:
value=[%s]"
,
pIndent,
pAttrib-
>
Name(
)
,
pAttrib-
>
Value(
)
)
;
if
(
pAttrib-
>
QueryIntValue(
&
ival)
=
=
TIXML_SUCCESS)
printf
(
"
int=%d"
,
ival)
;
if
(
pAttrib-
>
QueryDoubleValue(
&
dval)
=
=
TIXML_SUCCESS)
printf
(
"
d=%1.1f"
,
dval)
;
printf
(
"/n"
)
;
i+
+
;
pAttrib=
pAttrib-
>
Next(
)
;
}
return
i;
}
void
dump_to_stdout(
TiXmlNode*
pParent,
unsigned
int
indent =
0 )
{
if
(
!
pParent )
return
;
TiXmlNode*
pChild;
TiXmlText*
pText;
int
t =
pParent-
>
Type(
)
;
printf
(
"%s"
,
getIndent(
indent)
)
;
int
num;
switch
(
t )
{
case
TiXmlNode:
:
DOCUMENT:
printf
(
"Document"
)
;
break
;
case
TiXmlNode:
:
ELEMENT:
printf
(
"Element [%s]"
,
pParent-
>
Value(
)
)
;
num=
dump_attribs_to_stdout(
pParent-
>
ToElement(
)
,
indent+
1)
;
switch
(
num)
{
case
0:
printf
(
" (No attributes)"
)
;
break
;
case
1:
printf
(
"%s1 attribute"
,
getIndentAlt(
indent)
)
;
break
;
default
:
printf
(
"%s%d attributes"
,
getIndentAlt(
indent)
,
num)
;
break
;
}
break
;
case
TiXmlNode:
:
COMMENT:
printf
(
"Comment: [%s]"
,
pParent-
>
Value(
)
)
;
break
;
case
TiXmlNode:
:
UNKNOWN:
printf
(
"Unknown"
)
;
break
;
case
TiXmlNode:
:
TEXT:
pText =
pParent-
>
ToText(
)
;
printf
(
"Text: [%s]"
,
pText-
>
Value(
)
)
;
break
;
case
TiXmlNode:
:
DECLARATION:
printf
(
"Declaration"
)
;
break
;
default
:
break
;
}
printf
(
"/n"
)
;
for
(
pChild =
pParent-
>
FirstChild(
)
;
pChild !
=
0;
pChild =
pChild-
>
NextSibling(
)
)
{
dump_to_stdout(
pChild,
indent+
1
)
;
}
}
// load the named file and dump its structure to
STDOUT
void
dump_to_stdout(
const
char
*
pFilename)
{
TiXmlDocument doc(
pFilename)
;
bool
loadOkay =
doc.
LoadFile(
)
;
if
(
loadOkay)
{
printf
(
"/n%s:/n"
,
pFilename)
;
dump_to_stdout(
&
doc )
;
// defined later in the tutorial
}
else
{
printf
(
"Failed to load
file /"%s/"/n"
,
pFilename)
;
}
}
//
----------------------------------------------------------------------
// main() for printing files named on
the command line
//
----------------------------------------------------------------------
int
main(
int
argc,
char
*
argv[
]
)
{
for
(
int
i=
1;
i<
argc;
i+
+
)
{
dump_to_stdout(
argv[
i]
)
;
}
return
0;
}
|
在命令行或 DOS 窗口中這樣運行它,比如:
C:/dev/tinyxml>
Debug/tinyxml_1.
exe
example1.
xml
example1.
xml:
Document +
Declaration +
Element [
Hello]
(
No attributes)
+
Text: [
World]
|
作者以及變動