现在的位置: 首页 > 综合 > 正文

TinyXML 指南 二

2014年02月02日 ⁄ 综合 ⁄ 共 5279字 ⁄ 字号 评论关闭

开始

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

【上篇】
【下篇】

抱歉!评论已关闭.