- 论坛徽章:
- 0
|
TinyXML 指南
这是什么?
这份指南有一些关于如何有效地使用TinyXML的技巧和建议。
我也会尝试讲一些诸如怎样使字符串与整型数相互转化的C++技巧。这与TinyXML本身没什么关系,但它也许会对你的项目有所帮助,所以我还是把它加进来了。
如果你不知道基本的C++概念,那么这份指南就没什么用了。同样的,如果你不知道什么是DOM,那先从其它地方找来看看吧。
在我们开始之前
一些将会被用到的XML数据集/文件。
example1.xml:
World
example2.xml:
Alas
Great World
Alas (again)
example3.xml:
example4.xml:
Welcome to MyApp
Thank you for using MyApp
开始
把文件加载成XML
把一个文件加载成TinyXML DOM的最简单方法是:
TiXmlDocument doc( [color="#ff00ff"]"demo.xml" );
doc.LoadFile();
一个更接近于现实应用的例子如下。它加载文件并把内容显示到标准输出STDOUT上:
[color="#008000"]// 加载指定的文件并把它的结构输出到STDOUT上
[color="#0000ff"]void dump_to_stdout(const [color="#0000ff"]char* pFilename)
{
TiXmlDocument doc(pFilename);
[color="#0000ff"]bool loadOkay = doc.LoadFile();
[color="#0000ff"]if (loadOkay)
{
printf([color="#ff00ff"]"\n%s:\n", pFilename);
dump_to_stdout( &doc ); [color="#008000"]// 稍后在指南中定义
}
[color="#0000ff"]else
{
printf([color="#ff00ff"]"Failed to load file \"%s\”\n", pFilename);
}
}
在main中使用此函数的一个简单应用示范如下:
[color="#0000ff"]int main([color="#0000ff"]void)
{
dump_to_stdout([color="#ff00ff"]"example1.xml");
[color="#0000ff"]return 0;
}
回想example1的XML:
World
用这个XML运行程序就会在控制台/DOS窗口中显示:
DOCUMENT
+ DECLARATION
+ ELEMENT Hello
+ TEXT[World]
”dump_to_stdout“函数稍后会在这份指南中定义,如果你想要理解怎样递归遍历一个DOM它会很有用。
用程序建立文档对象
这是用程序建立example1的方法:
[color="#0000ff"]void build_simple_doc( )
{
[color="#008000"]// 生成xml: World
TiXmlDocument doc;
TiXmlDeclaration * decl = [color="#0000ff"]new TiXmlDeclaration( [color="#ff00ff"]"1.0", [color="#ff00ff"]"", [color="#ff00ff"]"" );
TiXmlElement * element = [color="#0000ff"]new TiXmlElement( [color="#ff00ff"]"Hello" );
TiXmlText * text = [color="#0000ff"]new TiXmlText( [color="#ff00ff"]"World" );
element->LinkEndChild( text );
doc.LinkEndChild( decl );
doc.LinkEndChild( element );
doc.SaveFile( [color="#ff00ff"]"madeByHand.xml" );
}
然后可以用以下方法加载并显示在控制台上:
dump_to_stdout([color="#ff00ff"]"madeByHand.xml"); [color="#008000"]// 此函数稍后会中指南中定义
你会看到跟example1一模一样:
madeByHand.xml:
Document
+ Declaration
+ Element [Hello]
+ Text: [World]
这段代码会产生相同的XML DOM,但它以不同的顺序来创建和链接结点:
[color="#0000ff"]void write_simple_doc2( )
{
[color="#008000"]// 实现与 write_simple_doc1一样的功能,(译注:我想它指是build_simple_doc)
[color="#008000"]// 但尽可能早地把结点添加到树中。
TiXmlDocument doc;
TiXmlDeclaration * decl = [color="#0000ff"]new TiXmlDeclaration( [color="#ff00ff"]"1.0", [color="#ff00ff"]"", [color="#ff00ff"]"" );
doc.LinkEndChild( decl );
TiXmlElement * element = [color="#0000ff"]new TiXmlElement( [color="#ff00ff"]"Hello" );
doc.LinkEndChild( element );
TiXmlText * text = [color="#0000ff"]new TiXmlText( [color="#ff00ff"]"World" );
element->LinkEndChild( text );
doc.SaveFile( [color="#ff00ff"]"madeByHand2.xml" );
}
两个都产生同样的XML,即:
World
结构构成都是:
DOCUMENT
+ DECLARATION
+ ELEMENT Hello
+ TEXT[World]
属性
给定一个存在的结点,设置它的属性是很容易的:
window = [color="#0000ff"]new TiXmlElement( [color="#ff00ff"]"Demo" );
window->SetAttribute([color="#ff00ff"]"name", [color="#ff00ff"]"Circle");
window->SetAttribute([color="#ff00ff"]"x", 5);
window->SetAttribute([color="#ff00ff"]"y", 15);
window->SetDoubleAttribute([color="#ff00ff"]"radius", 3.14159);
你也可以用TiXmlAttribute对象达到同样的目的。
下面的代码向我们展示了一种(并不只有一种)获取某一元素属性并打印出它们的名字和字符串值的方法,如果值能够被转化为整型数或者浮点数,也把值打印出来:
[color="#008000"]// 打印pElement的所有属性。
[color="#008000"]// 返回已打印的属性数量。
[color="#0000ff"]int dump_attribs_to_stdout(TiXmlElement* pElement, [color="#0000ff"]unsigned [color="#0000ff"]int indent)
{
[color="#0000ff"]if ( !pElement ) [color="#0000ff"]return 0;
TiXmlAttribute* pAttrib=pElement->FirstAttribute();
[color="#0000ff"]int i=0;
[color="#0000ff"]int ival;
[color="#0000ff"]double dval;
const [color="#0000ff"]char* pIndent=getIndent(indent);
printf([color="#ff00ff"]"\n");
[color="#0000ff"]while (pAttrib)
{
printf( [color="#ff00ff"]"%s%s: value=[%s]", pIndent, pAttrib->Name(), pAttrib->Value());
[color="#0000ff"]if (pAttrib->QueryIntValue(&ival)==TIXML_SUCCESS) printf( [color="#ff00ff"]" int=%d", ival);
[color="#0000ff"]if (pAttrib->QueryDoubleValue(&dval)==TIXML_SUCCESS) printf( [color="#ff00ff"]" d=%1.1f", dval);
printf( [color="#ff00ff"]"\n" );
i++;
pAttrib=pAttrib->Next();
}
[color="#0000ff"]return i;
}
把文档对象写到文件中
把一个已经建立好的DOM写到文件中是非常简单的:
doc.SaveFile( saveFilename );
回想一下,比如example4:
Welcome to MyApp
Thank you for using MyApp
以下函数建立这个DOM并把它写到“appsettings.xml”文件中:
[color="#0000ff"]void write_app_settings_doc( )
{
TiXmlDocument doc;
TiXmlElement* msg;
TiXmlDeclaration* decl = [color="#0000ff"]new TiXmlDeclaration( [color="#ff00ff"]"1.0", [color="#ff00ff"]"", [color="#ff00ff"]"" );
doc.LinkEndChild( decl );
TiXmlElement * root = [color="#0000ff"]new TiXmlElement( [color="#ff00ff"]"MyApp" );
doc.LinkEndChild( root );
TiXmlComment * comment = [color="#0000ff"]new TiXmlComment();
comment->SetValue([color="#ff00ff"]" Settings for MyApp " );
root->LinkEndChild( comment );
TiXmlElement * msgs = [color="#0000ff"]new TiXmlElement( [color="#ff00ff"]"Messages" );
root->LinkEndChild( msgs );
msg = [color="#0000ff"]new TiXmlElement( [color="#ff00ff"]"Welcome" );
msg->LinkEndChild( [color="#0000ff"]new TiXmlText( [color="#ff00ff"]"Welcome to MyApp" ));
msgs->LinkEndChild( msg );
msg = [color="#0000ff"]new TiXmlElement( [color="#ff00ff"]"Farewell" );
msg->LinkEndChild( [color="#0000ff"]new TiXmlText( [color="#ff00ff"]"Thank you for using MyApp" ));
msgs->LinkEndChild( msg );
TiXmlElement * windows = [color="#0000ff"]new TiXmlElement( [color="#ff00ff"]"Windows" );
root->LinkEndChild( windows );
TiXmlElement * window;
window = [color="#0000ff"]new TiXmlElement( [color="#ff00ff"]"Window" );
windows->LinkEndChild( window );
window->SetAttribute([color="#ff00ff"]"name", [color="#ff00ff"]"MainFrame");
window->SetAttribute([color="#ff00ff"]"x", 5);
window->SetAttribute([color="#ff00ff"]"y", 15);
window->SetAttribute([color="#ff00ff"]"w", 400);
window->SetAttribute([color="#ff00ff"]"h", 250);
TiXmlElement * cxn = [color="#0000ff"]new TiXmlElement( [color="#ff00ff"]"Connection" );
root->LinkEndChild( cxn );
cxn->SetAttribute([color="#ff00ff"]"ip", [color="#ff00ff"]"192.168.0.1");
cxn->SetDoubleAttribute([color="#ff00ff"]"timeout", 123.456); [color="#008000"]// 浮点数属性
dump_to_stdout( &doc );
doc.SaveFile( [color="#ff00ff"]"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默认以其它APIs称作“pretty”格式的方式来输出XML,对此我感到惊讶。这种格式修改了元素的文本结点中的空格,以使输出来的结点树包含一个嵌套层标记。
我还没有仔细看当写到一个文件中时是否有办法关闭这种缩进——这肯定很容易做到。(译注:这两句话大概是Ellers说的)
[Lee:在STL模式下这很容易做到,只需要cout XML与C++对象的相互转化
介绍
这个例子假设你在用一个XML文件来加载和保存你的应用程序配置,举例来说,有点像example4.xml。
有许多方法可以做到这点。例如,看看TinyBind项目:
http://sourceforge.net/projects/tinybind
这一节展示了一种普通老式的方法来使用XML加载和保存一个基本的对象结构。
建立你的对象类
从一些像这样的基本类开始:
[color="#ff0000"]#include
[color="#ff0000"]#include
[color="#0000ff"]using [color="#0000ff"]namespace [color="#0000ff"]std;
[color="#0000ff"]typedef [color="#0000ff"]std::map MessageMap;
[color="#008000"]// 基本的窗口抽象 - 仅仅是个示例
[color="#0000ff"]class WindowSettings
{
[color="#0000ff"]public:
[color="#0000ff"]int x,y,w,h;
[color="#0000ff"]string name;
WindowSettings()
: x(0), y(0), w(100), h(100), name([color="#ff00ff"]"Untitled")
{
}
WindowSettings([color="#0000ff"]int x, [color="#0000ff"]int y, [color="#0000ff"]int w, [color="#0000ff"]int h, const [color="#0000ff"]string& name)
{
[color="#0000ff"]this->x=x;
[color="#0000ff"]this->y=y;
[color="#0000ff"]this->w=w;
[color="#0000ff"]this->h=h;
[color="#0000ff"]this->name=name;
}
};
[color="#0000ff"]class ConnectionSettings
{
[color="#0000ff"]public:
[color="#0000ff"]string [color="#808000"]ip;
[color="#0000ff"]double timeout;
};
[color="#0000ff"]class AppSettings
{
[color="#0000ff"]public:
[color="#0000ff"]string m_name;
MessageMap m_messages;
[color="#0000ff"]list m_windows;
ConnectionSettings m_connection;
AppSettings() {}
[color="#0000ff"]void save(const [color="#0000ff"]char* pFilename);
[color="#0000ff"]void load(const [color="#0000ff"]char* pFilename);
[color="#008000"]// 仅用于显示它是如何工作的
[color="#0000ff"]void setDemoValues()
{
m_name=[color="#ff00ff"]"MyApp";
m_messages.clear();
m_messages[[color="#ff00ff"]"Welcome"]=[color="#ff00ff"]"Welcome to "+m_name;
m_messages[[color="#ff00ff"]"Farewell"]=[color="#ff00ff"]"Thank you for using "+m_name;
m_windows.clear();
m_windows.push_back(WindowSettings(15,15,400,250,[color="#ff00ff"]"Main"));
m_connection.ip=[color="#ff00ff"]"Unknown";
m_connection.timeout=123.456;
}
};
这是一个基本的mian(),它向我们展示了怎样创建一个默认的settings对象树,怎样保存并再次加载:
[color="#0000ff"]int main([color="#0000ff"]void)
{
AppSettings settings;
settings.save([color="#ff00ff"]"appsettings2.xml");
settings.load([color="#ff00ff"]"appsettings2.xml");
[color="#0000ff"]return 0;
}
接下来的main()展示了如何创建,修改,保存和加载一个settings结构:
[color="#0000ff"]int main([color="#0000ff"]void)
{
[color="#008000"]// 区块:定制并保存settings
{
AppSettings settings;
settings.m_name=[color="#ff00ff"]"HitchHikerApp";
settings.m_messages[[color="#ff00ff"]"Welcome"]=[color="#ff00ff"]"Don’t Panic";
settings.m_messages[[color="#ff00ff"]"Farewell"]=[color="#ff00ff"]"Thanks for all the fish";
settings.m_windows.push_back(WindowSettings(15,25,300,250,[color="#ff00ff"]"BookFrame"));
settings.m_connection.ip=[color="#ff00ff"]"192.168.0.77";
settings.m_connection.timeout=42.0;
settings.save([color="#ff00ff"]"appsettings2.xml");
}
[color="#008000"]// 区块:加载settings
{
AppSettings settings;
settings.load([color="#ff00ff"]"appsettings2.xml");
printf([color="#ff00ff"]"%s: %s\n", settings.m_name.c_str(),
settings.m_messages[[color="#ff00ff"]"Welcome"].c_str());
WindowSettings & w=settings.m_windows.front();
printf([color="#ff00ff"]"%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([color="#ff00ff"]"%s: %s\n", settings.m_name.c_str(),
settings.m_messages[[color="#ff00ff"]"Farewell"].c_str());
}
[color="#0000ff"]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
把C++状态编码成XML
有很多方法能够做到把文档对象保存到文件中,这就是其中一个:
[color="#0000ff"]void AppSettings::save(const [color="#0000ff"]char* pFilename)
{
TiXmlDocument doc;
TiXmlElement* msg;
TiXmlComment * comment;
[color="#0000ff"]string s;
TiXmlDeclaration* decl = [color="#0000ff"]new TiXmlDeclaration( [color="#ff00ff"]"1.0", [color="#ff00ff"]"", [color="#ff00ff"]"" );
doc.LinkEndChild( decl );
TiXmlElement * root = [color="#0000ff"]new TiXmlElement(m_name.c_str());
doc.LinkEndChild( root );
comment = [color="#0000ff"]new TiXmlComment();
s=[color="#ff00ff"]" Settings for "+m_name+[color="#ff00ff"]" ";
comment->SetValue(s.c_str());
root->LinkEndChild( comment );
[color="#008000"]// 区块:messages
{
MessageMap::iterator iter;
TiXmlElement * msgs = [color="#0000ff"]new TiXmlElement( [color="#ff00ff"]"Messages" );
root->LinkEndChild( msgs );
[color="#0000ff"]for (iter=m_messages.begin(); iter != m_messages.end(); iter++)
{
const [color="#0000ff"]string & key=(*iter).first;
const [color="#0000ff"]string & value=(*iter).second;
msg = [color="#0000ff"]new TiXmlElement(key.c_str());
msg->LinkEndChild( [color="#0000ff"]new TiXmlText(value.c_str()));
msgs->LinkEndChild( msg );
}
}
[color="#008000"]// 区块:windows
{
TiXmlElement * windowsNode = [color="#0000ff"]new TiXmlElement( [color="#ff00ff"]"Windows" );
root->LinkEndChild( windowsNode );
[color="#0000ff"]list::iterator iter;
[color="#0000ff"]for (iter=m_windows.begin(); iter != m_windows.end(); iter++)
{
const WindowSettings& w=*iter;
TiXmlElement * window;
window = [color="#0000ff"]new TiXmlElement( [color="#ff00ff"]"Window" );
windowsNode->LinkEndChild( window );
window->SetAttribute([color="#ff00ff"]"name", w.name.c_str());
window->SetAttribute([color="#ff00ff"]"x", w.x);
window->SetAttribute([color="#ff00ff"]"y", w.y);
window->SetAttribute([color="#ff00ff"]"w", w.w);
window->SetAttribute([color="#ff00ff"]"h", w.h);
}
}
[color="#008000"]// 区块:connection
{
TiXmlElement * cxn = [color="#0000ff"]new TiXmlElement( [color="#ff00ff"]"Connection" );
root->LinkEndChild( cxn );
cxn->SetAttribute([color="#ff00ff"]"ip", m_connection.ip.c_str());
cxn->SetDoubleAttribute([color="#ff00ff"]"timeout", m_connection.timeout);
}
doc.SaveFile(pFilename);
}
用修改过的main运行会生成这个文件:
Thanks for all the fish
Don't Panic
从XML中解码出状态
就像编码一样,也有许多方法可以让你从自己的C++对象结构中解码出XML。下面的方法使用了TiXmlHandles。
[color="#0000ff"]void AppSettings::load(const [color="#0000ff"]char* pFilename)
{
TiXmlDocument doc(pFilename);
[color="#0000ff"]if (!doc.LoadFile()) [color="#0000ff"]return;
TiXmlHandle hDoc(&doc);
TiXmlElement* pElem;
TiXmlHandle hRoot(0);
[color="#008000"]// 区块:name
{
pElem=hDoc.FirstChildElement().Element();
[color="#008000"]// 必须有一个合法的根结点,如果没有则温文地处理(译注:直接返回)
[color="#0000ff"]if (!pElem) [color="#0000ff"]return;
m_name=pElem->Value();
[color="#008000"]// 保存起来以备后面之用
hRoot=TiXmlHandle(pElem);
}
[color="#008000"]// 区块:string table
{
m_messages.clear(); [color="#008000"]// 清空已有的table
pElem=hRoot.FirstChild( [color="#ff00ff"]"Messages" ).FirstChild().Element();
[color="#0000ff"]for( pElem; pElem; pElem=pElem->NextSiblingElement())
{
const [color="#0000ff"]char *pKey=pElem->Value();
const [color="#0000ff"]char *pText=pElem->GetText();
[color="#0000ff"]if (pKey && pText)
{
m_messages[pKey]=pText;
}
}
}
[color="#008000"]// 区块:windows
{
m_windows.clear(); [color="#008000"]// 清空链表
TiXmlElement* pWindowNode=hRoot.FirstChild( [color="#ff00ff"]"Windows" )
.FirstChild().Element();
[color="#0000ff"]for( pWindowNode; pWindowNode;
pWindowNode=pWindowNode->NextSiblingElement())
{
WindowSettings w;
const [color="#0000ff"]char *pName=pWindowNode->Attribute([color="#ff00ff"]"name");
[color="#0000ff"]if (pName) w.name=pName;
pWindowNode->QueryIntAttribute([color="#ff00ff"]"x", &w.x); [color="#008000"]// 如果失败,原值保持现状
pWindowNode->QueryIntAttribute([color="#ff00ff"]"y", &w.y);
pWindowNode->QueryIntAttribute([color="#ff00ff"]"w", &w.w);
pWindowNode->QueryIntAttribute([color="#ff00ff"]"hh", &w.h);
m_windows.push_back(w);
}
}
[color="#008000"]// 区块:connection
{
pElem=hRoot.FirstChild([color="#ff00ff"]"Connection").Element();
[color="#0000ff"]if (pElem)
{
m_connection.ip=pElem->Attribute([color="#ff00ff"]"ip");
pElem->QueryDoubleAttribute([color="#ff00ff"]"timeout",&m_connection.timeout);
}
}
}
dump_to_stdout的完整列表
下面是一个可直接运行的示例程序,使用上面提到过的递归遍历方式,可用来加载任意的XML文件并把结构输出到STDOUT上。
[color="#008000"]// 指南示例程序
[color="#ff0000"]#include [color="#ff00ff"]"stdafx.h"
[color="#ff0000"]#include [color="#ff00ff"]"tinyxml.h"
[color="#008000"]// ———————————————————————-
[color="#008000"]// STDOUT输出和缩进实用函数
[color="#008000"]// ———————————————————————-
const [color="#0000ff"]unsigned [color="#0000ff"]int NUM_INDENTS_PER_SPACE=2;
const [color="#0000ff"]char * getIndent( [color="#0000ff"]unsigned [color="#0000ff"]int numIndents )
{
[color="#0000ff"]static const [color="#0000ff"]char * pINDENT=[color="#ff00ff"]" + ";
[color="#0000ff"]static const [color="#0000ff"]unsigned [color="#0000ff"]int LENGTH=strlen( pINDENT );
[color="#0000ff"]unsigned [color="#0000ff"]int n=numIndents*NUM_INDENTS_PER_SPACE;
[color="#0000ff"]if ( n > LENGTH ) n = LENGTH;
[color="#0000ff"]return &pINDENT[ LENGTH-n ];
}
[color="#008000"]// 与getIndent相同,但最后没有“+”
const [color="#0000ff"]char * getIndentAlt( [color="#0000ff"]unsigned [color="#0000ff"]int numIndents )
{
[color="#0000ff"]static const [color="#0000ff"]char * pINDENT=[color="#ff00ff"]" ";
[color="#0000ff"]static const [color="#0000ff"]unsigned [color="#0000ff"]int LENGTH=strlen( pINDENT );
[color="#0000ff"]unsigned [color="#0000ff"]int n=numIndents*NUM_INDENTS_PER_SPACE;
[color="#0000ff"]if ( n > LENGTH ) n = LENGTH;
[color="#0000ff"]return &pINDENT[ LENGTH-n ];
}
[color="#0000ff"]int dump_attribs_to_stdout(TiXmlElement* pElement, [color="#0000ff"]unsigned [color="#0000ff"]int indent)
{
[color="#0000ff"]if ( !pElement ) [color="#0000ff"]return 0;
TiXmlAttribute* pAttrib=pElement->FirstAttribute();
[color="#0000ff"]int i=0;
[color="#0000ff"]int ival;
[color="#0000ff"]double dval;
const [color="#0000ff"]char* pIndent=getIndent(indent);
printf([color="#ff00ff"]"\n");
[color="#0000ff"]while (pAttrib)
{
printf( [color="#ff00ff"]"%s%s: value=[%s]", pIndent, pAttrib->Name(), pAttrib->Value());
[color="#0000ff"]if (pAttrib->QueryIntValue(&ival)==TIXML_SUCCESS) printf( [color="#ff00ff"]" int=%d", ival);
[color="#0000ff"]if (pAttrib->QueryDoubleValue(&dval)==TIXML_SUCCESS) printf( [color="#ff00ff"]" d=%1.1f", dval);
printf( [color="#ff00ff"]"\n" );
i++;
pAttrib=pAttrib->Next();
}
[color="#0000ff"]return i;
}
[color="#0000ff"]void dump_to_stdout( TiXmlNode* pParent, [color="#0000ff"]unsigned [color="#0000ff"]int indent = 0 )
{
[color="#0000ff"]if ( !pParent ) [color="#0000ff"]return;
TiXmlNode* pChild;
TiXmlText* pText;
[color="#0000ff"]int t = pParent->Type();
printf( [color="#ff00ff"]"%s", getIndent(indent));
[color="#0000ff"]int num;
[color="#0000ff"]switch ( t )
{
[color="#0000ff"]case TiXmlNode::DOCUMENT:
printf( [color="#ff00ff"]"Document" );
[color="#0000ff"]break;
[color="#0000ff"]case TiXmlNode::ELEMENT:
printf( [color="#ff00ff"]"Element [%s]", pParent->Value() );
num=dump_attribs_to_stdout(pParent->ToElement(), indent+1);
[color="#0000ff"]switch(num)
{
[color="#0000ff"]case 0: printf( [color="#ff00ff"]" (No attributes)"); [color="#0000ff"]break;
[color="#0000ff"]case 1: printf( [color="#ff00ff"]"%s1 attribute", getIndentAlt(indent)); [color="#0000ff"]break;
[color="#0000ff"]default: printf( [color="#ff00ff"]"%s%d attributes", getIndentAlt(indent), num); [color="#0000ff"]break;
}
[color="#0000ff"]break;
[color="#0000ff"]case TiXmlNode::COMMENT:
printf( [color="#ff00ff"]"Comment: [%s]", pParent->Value());
[color="#0000ff"]break;
[color="#0000ff"]case TiXmlNode::UNKNOWN:
printf( [color="#ff00ff"]"Unknown" );
[color="#0000ff"]break;
[color="#0000ff"]case TiXmlNode::TEXT:
pText = pParent->ToText();
printf( [color="#ff00ff"]"Text: [%s]", pText->Value() );
[color="#0000ff"]break;
[color="#0000ff"]case TiXmlNode::DECLARATION:
printf( [color="#ff00ff"]"Declaration" );
[color="#0000ff"]break;
[color="#0000ff"]default:
[color="#0000ff"]break;
}
printf( [color="#ff00ff"]"\n" );
[color="#0000ff"]for ( pChild = pParent->FirstChild(); pChild != 0; pChild = pChild->NextSibling())
{
dump_to_stdout( pChild, indent+1 );
}
}
[color="#008000"]// 加载指定的文件并把它的结构输出到STDOUT上
[color="#0000ff"]void dump_to_stdout(const [color="#0000ff"]char* pFilename)
{
TiXmlDocument doc(pFilename);
[color="#0000ff"]bool loadOkay = doc.LoadFile();
[color="#0000ff"]if (loadOkay)
{
printf([color="#ff00ff"]"\n%s:\n", pFilename);
dump_to_stdout( &doc );
}
[color="#0000ff"]else
{
printf([color="#ff00ff"]"Failed to load file \"%s\”\n", pFilename);
}
}
[color="#008000"]// ———————————————————————-
[color="#008000"]// main(),打印出从命令行指定的文件
[color="#008000"]// ———————————————————————-
[color="#0000ff"]int main([color="#0000ff"]int argc, [color="#0000ff"]char* argv[])
{
[color="#0000ff"]for ([color="#0000ff"]int i=1; iC:\dev\tinyxml> Debug\tinyxml_1.exe example1.xml
example1.xml:
Document
+ Declaration
+ Element [Hello]
(No attributes)
+ Text: [World]
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/102400/showart_2031563.html |
|