TinyXML 指南 二

开始

把文件加载成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”格式了,加多一个开关是一个很好的特性,这已经被要求过了。]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值