开始
把文件加载成XML
把一个文件加载成TinyXML DOM的最简单方法是:
TiXmlDocument doc( "demo.xml" );
doc.LoadFile();
一个更接近于现实应用的例子如下。它加载文件并把内容显示到标准输出STDOUT上:
// 加载指定的文件并把它的结构输出到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 ); // 稍后在指南中定义
}
else
{
printf("Failed to load file /" %s/”/n", pFilename);
}
}
在main中使用此函数的一个简单应用示范如下:
int main(void )
{
dump_to_stdout("example1.xml" );
return 0;
}
回想example1的XML:
<?xml version="1.0" ?>
<Hello>World</Hello>
用这个XML运行程序就会在控制台/DOS窗口中显示:
DOCUMENT
+ DECLARATION
+ ELEMENT Hello
+ TEXT[World]
”dump_to_stdout“函数稍后会在这份指南中定义,如果你想要理解怎样递归遍历一个DOM它会很有用。
用程序建立文档对象
这是用程序建立example1的方法:
void build_simple_doc( )
{
// 生成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" ); // 此函数稍后会中指南中定义
你会看到跟example1一模一样:
madeByHand.xml:
Document
+ Declaration
+ Element [Hello]
+ Text: [World]
这段代码会产生相同的XML DOM,但它以不同的顺序来创建和链接结点:
void write_simple_doc2( )
{
// 实现与 write_simple_doc1一样的功能,(译注:我想它指是build_simple_doc )
// 但尽可能早地把结点添加到树中。
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对象达到同样的目的。
下面的代码向我们展示了一种(并不只有一种)获取某一元素属性并打印出它们的名字和字符串值的方法,如果值能够被转化为整型数或者浮点数,也把值打印出来:
// 打印pElement的所有属性。
// 返回已打印的属性数量。
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 );
回想一下,比如example4:
<?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); // 浮点数属性
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默认以其它APIs称作“pretty”格式的方式来输出XML,对此我感到惊讶。这种格式修改了元素的文本结点中的空格,以使输出来的结点树包含一个嵌套层标记。
我还没有仔细看当写到一个文件中时是否有办法关闭这种缩进——这肯定很容易做到。(译注:这两句话大概是Ellers说的 )
[Lee:在STL模式下这很容易做到,只需要cout << myDoc就行了。在非STL模式下就总是用“pretty”格式了,加多一个开关是一个很好的特性,这已经被要求过了。]