TinyXml-2 Tutorial 中文翻译
2017-08-22 16:26
363 查看
原文地址 http://www.grinninglizard.com/tinyxmldocs/tutorial0.html
本文将包含一些C++的小技巧例如转换字符串到整型或反过来。这些技巧和TinyXML本身没有啥联系,但是也许会给你的project些许帮助。
如果你不清楚基本的C++概念那么这篇教程就对你没啥用。同样的如果你对DOM是什么感到模糊,建议先查阅一下DOM的资料。
W3C的DOM教程
example1.xml:
example2.xml:
example3.xml:
example4.xml
一个更现实点的方式如下。该方式是将会载入该文件并该XML打印到STDOUT:
一个使用dump_to_stdout函数的演示如下:
EXAMPLE 1 XML 是:
运行上面的main函数将会打印以下内容到 控制台/DOS窗口:
生成的XML可被如下函数载入并显示到控制台:
你会发现打印结果和 Example 1是一样的:
下述代码可生成完全相同的XML DOM,但是他的节点NODE建立和连接顺序并不相同(其实就是一个先全部定义后再连接,下面这个是一建立后就连接):
以上两种方式都产生完全一样的XML
Both of these produce the same XML, 也就是说:
或者描述成以下格式:
你也可以使用TiXmlAttribute对象来完成操作。
以下代码演示了得到一个Element(元素)所有的Attributes(属性),并打印它们的 name(名称)和string(字符串)值,并且如果该值可由一个int转换成double值,把该double值也打印出来。
回忆 example 4:
以下代码建立了如上的DOM并将之写入到文件“appsettings.xml”:
dump_to_stdout 函数将会打印出以下结构:
我很惊讶于TinyXML默认情况下就可以写出让其他API称赞为“完美”格式的XML排版-它调整了element文本(TEXT)的空格数量,从而让它看起来包含了其他节点Node,这样的话在写出其树形结构的时候可以非常清晰的看出其嵌套结构。
我还没有看到在编写文件时是否有办法关闭缩进,但这是很容易实现的。
[Lee(原文作者): 使用STL模式是很简单的,仅仅只需要cout << myDoc. NON-STL 模式 总是会是”完美” 格式。 添加一个 switch 将会是一个非常棒的featrue,并且也是这样要求的.]
以下待翻译~~~~~~~~~~~~~~~~~~~~
例如 像example4.xml那样的。
有许多种方法可以达成这个目的。例如,参考这个TinyBind项目
http://sourceforge.net/projects/tinybind
这部分展示了使用XML的老式方法来保存并载入基本的对象结构。
这个基础的main()展示了怎么建立一个默认的设置对象树(default settings object tree),再次保存并载入它:
接下来的main()展示了如何使用设置结构体(settings structure)创建、修改、保存、载入:
当完成save()和load()操作后,运行main()将会在控制台打印如下结果:
运行修改后的main()将会产出以下文件:
##完整的dump_to_stdout函数
以下是 载入随机XML文件并使用 迭代遍历 来将其结构打印到STDOUT的演示例子
Authors and Changes
Written by Ellers, April, May, June 2005
Minor edits and integration into doc system, Lee Thomason September 2005
Updated by Ellers, October 2005
什么是TinyXml?
该教程会包含一些怎么高效使用TinyXML的提示和建议。本文将包含一些C++的小技巧例如转换字符串到整型或反过来。这些技巧和TinyXML本身没有啥联系,但是也许会给你的project些许帮助。
如果你不清楚基本的C++概念那么这篇教程就对你没啥用。同样的如果你对DOM是什么感到模糊,建议先查阅一下DOM的资料。
W3C的DOM教程
开始之前
以下是一些我们将要使用的 XML文件样例example1.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="40 4000 0" h="250" /> </Windows> <Connection ip="192.168.0.1" timeout="123.456000" /> </MyApp>
开始教程
从文件中载入XML
最简单的载入文件为TinyXML DOM的方式为:TiXmlDocument doc( "demo.xml" ); doc.LoadFile();
一个更现实点的方式如下。该方式是将会载入该文件并该XML打印到STDOUT:
// 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); } }
一个使用dump_to_stdout函数的演示如下:
int main(void) { dump_to_stdout("example1.xml"); return 0; }
EXAMPLE 1 XML 是:
<?xml version="1.0" ?> <Hello>World</Hello>
运行上面的main函数将会打印以下内容到 控制台/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 do c; 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" ); }
生成的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,但是他的节点NODE建立和连接顺序并不相同(其实就是一个先全部定义后再连接,下面这个是一建立后就连接):
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
Both of these produce the same XML, 也就是说:
<?xml version="1.0" ?> <Hello>World</Hello>
或者描述成以下格式:
DOCUMENT + DECLARATION + ELEMENT Hello + TEXT[World]
Attributes(属性)
给出一个已存在的节点NODE,设置它的属性是非常容易的:window = new TiXmlElement( "Demo" ); window->SetAttribute("name", "Circle"); window->SetAttribute("x", 5); window->SetAttribute("y", 15); window->SetDoubleAttribute("radius", 3.14159);
你也可以使用TiXmlAttribute对象来完成操作。
以下代码演示了得到一个Element(元素)所有的Attributes(属性),并打印它们的 name(名称)和string(字符串)值,并且如果该值可由一个int转换成double值,把该double值也打印出来。
// 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; }
将XML文档写入到文件中
将一个提前建立好的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排版-它调整了element文本(TEXT)的空格数量,从而让它看起来包含了其他节点Node,这样的话在写出其树形结构的时候可以非常清晰的看出其嵌套结构。
我还没有看到在编写文件时是否有办法关闭缩进,但这是很容易实现的。
[Lee(原文作者): 使用STL模式是很简单的,仅仅只需要cout << myDoc. NON-STL 模式 总是会是”完美” 格式。 添加一个 switch 将会是一个非常棒的featrue,并且也是这样要求的.]
以下待翻译~~~~~~~~~~~~~~~~~~~~
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()展示了怎么建立一个默认的设置对象树(default settings object tree),再次保存并载入它:
int main(void) { AppSettings settings; settings.save("appsettings2.xml"); settings.load("appsettings2.xml"); return 0; }
接下来的main()展示了如何使用设置结构体(settings structure)创建、修改、保存、载入:
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
将C++状态(state)代码编码至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'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>
将状态(state)从XML解码至C++
有许多种方法将一个已编码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文件并使用 迭代遍历 来将其结构打印到STDOUT的演示例子
// 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;
}
Run this from the command line or a DOS window, e.g.:
C:\dev\tinyxml> Debug\tinyxml_1.exe example1.xml
example1.xml:
Document
+ Declaration
+ Element [Hello]
(No attributes)
+ Text: [World]
Authors and Changes
Written by Ellers, April, May, June 2005
Minor edits and integration into doc system, Lee Thomason September 2005
Updated by Ellers, October 2005
相关文章推荐
- j2ee1.4 tutorial的中文翻译
- Gevent tutorial (Gevent中文教程,Gevent中文翻译)
- db4o Tutorial 中文翻译(七)
- db4o Tutorial 中文翻译(八)
- Recurrent Neural Networks Tutorial 中文翻译
- db4o Tutorial 中文翻译(九)
- Gevent tutorial (Gevent中文教程,Gevent中文翻译)(转载)
- db4o Tutorial 中文翻译(十)
- db4o Tutorial 中文翻译(十一)
- Mercury QuickTest Professional Tutorial [翻译] (一)
- Be Smart!敏捷/明智开发--2008CSDN中国软件英雄会Ivar Jacobson博士讲义(中文翻译完整版)
- Jabber/XMPP中文翻译计划
- jQuery中文入门指南,翻译加实例,jQuery的起点教程
- Samba-HOWTO-Collection中文翻译版(2.20)
- BIOS设置 翻译中文图文教程(二)
- 《Entity Framework 6 Recipes》中文翻译系列 (30) ------ 第六章 继承与建模高级应用之多对多关联
- NodeMCU文档中文翻译 7 DHT温湿度传感器模块
- Fuck XMPP (4) Jabber/XMPP中文翻译计划
- 《Entity Framework 6 Recipes》中文翻译系列 (36) ------ 第六章 继承与建模高级应用之TPC继承映射