这几天在埋头写自己的个星期!而且由于它是基于事件发生的次序(小时就把我的文件导出来了~~呵呵。在阅读本文之前,请先看看我Blog里转贴的《TinyXML学习笔记》,相信它能给各位一个关于TinyXML的初步概念。

言归正传,本文目的在于补全之前《TinyXML学习》的不足,尽量把常用的示例代码列出让大家参考。此外,在本篇最后会给出一个完整的文件读写例子,供读者参考。

1. 编程环境的设置。新建一个项目,起名叫TestTXML。到http://sourceforge.net/projects/tinyxml/下载TinyXML的官方例子,并编译第一个Project
tinyxml(注意,最好编译Release的版本,代码比较小。然后把生成的tinyxml.lib(如果是Debug版本,叫tinyxmld.lib)连同tinystr.h和tinyxml.h一起Copy到TestTXML项目的目录中。在TestTXML项目里的头文件加入对TinyXML的引用:

#pragma comment(lib,"tinyxml.lib")
// 链接Library

#include "tinyxml.h" // TinyXML的头文件

2. 建立一个XML文件:

char* sFilePath = "ikk_doc.xml"; // 文件名称

TiXmlDocument xmlDoc( sFilePath ); // 建立一个XML文件

TiXmlDeclaration Declaration( "1.0","gb2312", "yes" ); // 声明XML的属性

xmlDoc.InsertEndChild( Declaration ); // 写入基本的XML头结构

xmlDoc.SaveFile(); // 把XML文件写入硬盘

这时,在硬盘上的TestXML项目目录里,ikk_doc.xml文件已经被创建出来了。

3. 在XML文件里插入Element

所谓的Element,就是在XML里面的Tag,例如在<resume
name=”裕作”>简历内容</resume>中,“Resume”就是Element的名字,上述的整个字符串就是一个Element。在TinyXML里,插入Element的步骤如下:

TiXmlElement* pElm = NULL;

pElm = new TiXmlElement( "resumes" ); //定义当前的子节点 pElmParent.InsertEndChild(
*pElm ); // 把子节点插入父节点中

4. 在element里插入属性。在刚才例子中,name=”裕作”就是Resume的属性,其中name是属性的名字,”裕作”是属性的值。在当前子节点内插入属性的方法如下:

pElm->SetAttribute( "name", resume.sName );

5. 在XML里插入文本。在<resume
name=”裕作”>简历内容</resume>中,“简历内容”就是一段文本,事实上,在TinyXML里,它是被当作一个Text类型的子节点来插入的。还而言之,就是在Resume的子节点中,插入这个Text子节点。插入例子如下:

TiXmlText* pText = NULL; 

pText = new TiXmlText( "简历内容" ); // 定义文本的内容

pElmChild->InsertEndChild( *pText ); //把text子节点插入父节点中

在具备了以上背景知识之后,我们已经可以用TinyXML读写一个XML文件了。本文最后的程序将写入,然后重新读取一个XML文件到我们的结构里。这个XML文件的内容如下:

<?xml version="1.0" encoding="GB2312" ?>

<resumes>

<resume name="裕作">

<gender>男</gender>

<age>26</age>

<skills
num="2">

<skill
level="99">编程</skill>

<skill
level="1">吹牛</skill>

</skills>

</resume>

<resume
name="裕作 The Great">

<gender>男</gender>

<age>0</age>

<skills
num="1">

<skill
level="100">编程</skill>

</skills>

</resume>

</resumes>

以下程序将建立ikk_doc.xml文件,然后重新把内容读取进内存:

#pragma comment(lib,"tinyxml.lib")

#include "string.h"

#include "stdio.h"

#include "tinyxml.h"

#define XML_FILE "ikk_doc.xml"

#define NAME_LENGTH 256 // 名字类字符的分配长度

#define SAFE_DELETE(x) {if(x) delete x; x=NULL;} // 安全删除new分配出来的变量空间

#define SAFE_DELETE_ARRAY(x) {if(x) delete[] x; x=NULL;} // 安全删除new分配出来的数组空间

#define XML_HEADER "<?xml version=\"1.0\" encoding=\"GB2312\" ?>" // XML文件头的定义

typedef unsigned int uint32;

// 技能的结构

typedef struct skill_s {

uint32
nLevel; // 技能的程度

char
sName[ NAME_LENGTH ]; // 技能的名称

skill_s()
{

nLevel
= 0;

sName[0]
= 0;

}

} skill_t;

// 简历的结构

typedef struct resume_s {

char
sName[ NAME_LENGTH ]; // 名字

bool
isMan; // 是否男性

uint32
nAge; // 年龄

uint32
nNumSkill; // 技能的数目

skill_t*
pSkill; // 技能的结构

resume_s()
{

sName[0]
= 0;

isMan
= false;

nAge
= 0;

nNumSkill
= 0;

pSkill
= NULL;

}

} resume_t;

void exportSkill( TiXmlElement* pElmParent, skill_t skill )

{

int
i;

char
sBuf[NAME_LENGTH]; // 一个临时存放的字符串

TiXmlElement*
pElm = NULL; // 一个指向Element的指针

TiXmlText*
pText = NULL; // 一个指向Text的指针

pElm
= new TiXmlElement( "skill" );

// 插入等级(以属性形式)

sprintf(
sBuf, "%d", skill.nLevel ); // 把Skill的登记变成字符串临时存进sBuf里

pElm->SetAttribute(
"level", sBuf ); // 把等级插入Skill里

// 插入技能名称(以子Element形式)

pText
= new TiXmlText( skill.sName ); // 建立一个Skill的子Element(一个Text形式的子元素)

pElm->InsertEndChild(
*pText ); // 把这个Skill的子Element插入Skill里

SAFE_DELETE(
pText ); // 删除这个Text

// 最后把整个Resume的子节点插入到父节点中

pElmParent->InsertEndChild(
*pElm );

}

void importSkill( TiXmlElement*
pElm, skill_t* pSkill )

{

int
i;

char
sBuf[NAME_LENGTH]; // 一个临时存放的字符串

TiXmlElement*
pElmChild = NULL; // 一个指向Element的指针

TiXmlText*
pText = NULL; // 一个指向Text的指针

// 读取level

pSkill->nLevel
= atoi( pElm->Attribute( "level" ) );

// 读取技能名称

strcpy(
pSkill->sName, pElm->FirstChild()->Value() );

}

void exportResume( TiXmlElement* pElmParent, resume_t resume )

{

int
i;

char
sBuf[NAME_LENGTH]; // 一个临时存放的字符串

TiXmlElement*
pElm = NULL; // 一个指向Element的指针

TiXmlElement*
pElmChild = NULL; // 一个指向Element的指针

TiXmlText*
pText = NULL; // 一个指向Text的指针

pElm
= new TiXmlElement( "resume" );

// 插入名字(以属性形式)

pElm->SetAttribute(
"name", resume.sName );

// 插入性别(以子Element形式)

pElmChild
= new TiXmlElement( "gender" ); // 建立一个子Element叫Gender

if(
resume.isMan )

pText
= new TiXmlText( "男" ); // 建立一个Gender的子Element(一个Text形式的子元素)

else

pText
= new TiXmlText( "女" ); // 建立一个Gender的子Element(一个Text形式的子元素)

pElmChild->InsertEndChild(
*pText ); // 把这个Gender的子Element插入Gender里

pElm->InsertEndChild(
*pElmChild ); // 把Gender插入到主Element里

SAFE_DELETE(
pElmChild ); // 删除已经用完的Gender

SAFE_DELETE(
pText ); // 删除这个Text

// 插入年龄(以子Element形式)

pElmChild
= new TiXmlElement( "age" ); // 建立一个子Element叫Age

sprintf(
sBuf, "%d", resume.nAge ); // 把Age变成字符串临时存进sBuf里

pText
= new TiXmlText( sBuf ); // 建立一个Age的子Element(一个Text形式的子元素)

pElmChild->InsertEndChild(
*pText ); // 把这个Age的子Element插入Age里

pElm->InsertEndChild(
*pElmChild ); // 把Age插入到主Element里

SAFE_DELETE(
pElmChild ); // 删除已经用完的Age

SAFE_DELETE(
pText ); // 删除这个Text

// 插入技能子节点

pElmChild
= new TiXmlElement( "skills" ); // 建立一个子Element叫Skills

sprintf(
sBuf, "%d", resume.nNumSkill ); // 把Skill的数目变成字符串临时存进sBuf里

pElmChild->SetAttribute(
"num", sBuf ); // 把这个Skills的属性插入Skills里

for(
i=0; i<resume.nNumSkill; i++ )

{

exportSkill(
pElmChild, resume.pSkill[i] ); // 插入一项技能

}

pElm->InsertEndChild(
*pElmChild ); // 把Skills插入到主Element里

SAFE_DELETE(
pElmChild ); // 删除已经用完的Skills

SAFE_DELETE(
pText ); // 删除这个Text

// 最后把整个Resume的子节点插入到父节点中

pElmParent->InsertEndChild(
*pElm );

SAFE_DELETE(
pElm ); // 删除子节点

}

void importResume( TiXmlElement* pElm, resume_t* pResume )

{

int
i;

char
sBuf[NAME_LENGTH]; // 一个临时存放的字符串

TiXmlElement*
pElmChild = NULL; // 一个指向Element的指针

TiXmlElement*
pElmGrandChild = NULL; // 一个指向Element的指针

TiXmlText*
pText = NULL; // 一个指向Text的指针

// 读入"resume"子节点

strcpy(
pResume->sName, pElm->Attribute( "name" ) );

// 读入"gender"子节点

pElmChild
= pElm->FirstChildElement( "gender" );

if(
strcmp( "男", pElmChild->FirstChild()->Value() ) == 0 )

pResume->isMan
= true;

else

pResume->isMan
= false;

// 读入"age"子节点

pElmChild
= pElm->FirstChildElement( "age" );

pResume->nAge
= atoi( pElmChild->FirstChild()->Value() );

// 读入"skills"子节点

pElmChild
= pElm->FirstChildElement( "skills" );

pResume->nNumSkill
= atoi( pElmChild->Attribute( "num" ) );

pResume->pSkill
= new skill_t[pResume->nNumSkill];

pElmGrandChild
= pElmChild->FirstChildElement( "skill" ); // 指向第一个Skill

for(
i=0; i<pResume->nNumSkill; i++ ) {

importSkill(
pElmGrandChild, &(pResume->pSkill[i]) ); // 读取一个Skill

pElmGrandChild
= pElmGrandChild->NextSiblingElement(); // 指向下一个Skill

}

}

bool readXML( char* sFilePath, int* nNumResume, resume_t** ppResume )     {

int
i; // 用做循环的变量

TiXmlElement*
pElmChild = NULL; // 一个指向Element的指针

TiXmlDocument
xmlDoc( sFilePath ); // 输入XML路径

if(
!xmlDoc.LoadFile() ) // 读取XML并检查是否读入正确

return
false;

TiXmlElement*
pElmRoot = NULL; // 根节点

pElmRoot
= xmlDoc.FirstChildElement( "resumes" ); // 得到根节点

if(
!pElmRoot ) {

return
false;

}

*nNumResume
= atoi( pElmRoot->Attribute( "num" ) ); // 读取Resume的数目

*ppResume
= new resume_t[*nNumResume]; // 分配Resume的空间

pElmChild
= pElmRoot->FirstChildElement( "resume" ); // 找出第一个Resume

for(
i=0; i<*nNumResume; i++ ) {

importResume(
pElmChild, &((*ppResume)[i]) ); // 读取Resume的内容

pElmChild
= pElmChild->NextSiblingElement(); // 找出下一个Resume

}

return
true;

}

bool writeXML( char* sFilePath, int nNumResume, resume_t* pResume )

    {

if(
!sFilePath || !pResume )

return
false; // 确定指针存在

int
i; // 用做循环的变量

char
sBuf[NAME_LENGTH]; // 一个临时存放的字符串

TiXmlElement*
pElm = NULL; // 一个指向Element的指针

TiXmlDeclaration
Declaration( "1.0","gb2312", "yes" ); // 建立XML头结构

TiXmlDocument
xmlDoc( sFilePath ); // 用存档的文件名字来建立一个XML文件

xmlDoc.InsertEndChild(
Declaration ); // 把XML头结构插入当前文档



        // 插入根节点“Resumes”

        pElm
= new TiXmlElement( "resumes" ); // 建立根节点“Resumes”

        sprintf(
sBuf, "%d", nNumResume ); // 把nNumResume变成字符串临时存进sBuf里

pElm->SetAttribute(
"num", sBuf ); // 建立一个Resumes的子Element

for(
i=0; i<2; i++ )

        {

            exportResume(
pElm, pResume[i] ); // 在根节点上插入以上定义的2个简历

        }

        xmlDoc.InsertEndChild(
*pElm );

xmlDoc.SaveFile();

SAFE_DELETE(
pElm ); // 删除Element

return
true;

}

void main()

{

int
i, j;

//
+ == 设置两份简历 ==========================================================

int
nNumResume = 2;

resume_t*
pResume = new resume_t[ nNumResume ];

//
1. 初始化第一份简历

strcpy(
pResume[0].sName, "裕作" );

pResume[0].isMan
= true;

pResume[0].nAge
= 26;

pResume[0].nNumSkill
= 2;

pResume[0].pSkill
= new skill_t[2];

{
// 设置技能列表结构

strcpy(
pResume[0].pSkill[0].sName, "编程" );

strcpy(
pResume[0].pSkill[1].sName, "吹牛" );

pResume[0].pSkill[0].nLevel
= 99;

pResume[0].pSkill[1].nLevel
= 1;

}

//
2. 初始化第二份简历

strcpy(
pResume[1].sName, "裕作 The Great" );

pResume[1].isMan
= true;

pResume[1].nAge
= 0;

pResume[1].nNumSkill
= 1;

pResume[1].pSkill
= new skill_t[1];

{
// 设置技能列表结构

strcpy(
pResume[1].pSkill[0].sName, "编程" );

pResume[1].pSkill[0].nLevel
= 100;

}

//
- == 设置两份简历 ==========================================================

// 把简历以XML形式写入磁盘

if(
!writeXML( XML_FILE, nNumResume, pResume ) )

{

printf(
"ERROR: can't write the file." );

return;

}

// 删除Resume

nNumResume
= 0;

SAFE_DELETE_ARRAY(
pResume );

// 重新读入XML文件里的Resume数据

if(
!readXML( XML_FILE, &nNumResume, &pResume ) )

{

printf(
"ERROR: can't read the file." );

return;

}

// 把所有简历输出到屏幕

if(
pResume ) // 确定有Resume

{

for(
i=0; i<nNumResume; i++ ) {

printf(
"简历:======================\n" );

printf(
"\t名字:%s\n", pResume[i].sName );

if(
pResume[i].isMan )

printf(
"\t性别:男\n" );

else

printf(
"\t性别:女\n" );

printf(
"\t年龄:%d\n", pResume[i].nAge );

printf(
"\t职业技能:\n" );

for(
j=0; j<pResume[i].nNumSkill; j++ ) {

printf(
"\t\t技能名称:%s\n", pResume[i].pSkill[j].sName );

printf(
"\t\t技能等级:%d\n", pResume[i].pSkill[j].nLevel );

}

}

}

}

tiny学习3的更多相关文章

  1. 【TencentOS tiny】又有一个操作系统开源

    新闻 2019年9月18日,腾讯宣布将开源 自主研发的轻量级物联网实时操作系统TencentOS tiny.相比市场上其它系统,腾讯TencentOS tiny在资源占用.设备成本.功耗管理以及安全稳 ...

  2. 【TencentOS tiny】深度源码分析(4)——消息队列

    消息队列 在前一篇文章中[TencentOS tiny学习]源码分析(3)--队列 我们描述了TencentOS tiny的队列实现,同时也点出了TencentOS tiny的队列是依赖于消息队列的, ...

  3. RTX51 Tiny实时操作系统学习笔记—初识RTX51 Tiny

     一,RTX51 Tiny简单介绍    RTX51 Tiny是一种实时操作系统(RTOS),能够用它来建立多个任务(函数)同一时候运行的应用(从宏观上看是同一时候运行的,但从微观上看,还是独立运行的 ...

  4. Unity Tiny & ECS 学习笔记

    1.官方文档 https://docs.unity3d.com/Packages/com.unity.tiny@0.13/manual/intro-for-unity-developers.html ...

  5. Tiny 6410的Linux学习总结!

    1.Tiny6410的Linux系统修改IP地址:         vi /etc/eth0-setting 2.Ubuntu14.04自动以root身份登录系统:  /etc/lightdm/lig ...

  6. 【深度学习Deep Learning】资料大全

    最近在学深度学习相关的东西,在网上搜集到了一些不错的资料,现在汇总一下: Free Online Books  by Yoshua Bengio, Ian Goodfellow and Aaron C ...

  7. GitHub 上 57 款最流行的开源深度学习项目

    转载:https://www.oschina.net/news/79500/57-most-popular-deep-learning-project-at-github GitHub 上 57 款最 ...

  8. 学习OpenStack之(5):在Mac上部署Juno版本OpenStack 四节点环境

    0. 前沿 经过一段时间的折腾,终于在自己的Mac上装好了Juno版本的四节点环境.这过程中,花了大量的时间,碰到了许多问题,学到不少知识,折腾过不少其实不需要折腾的东西,本文试着来对这过程做个总结. ...

  9. 值得学习的C语言开源项目

    值得学习的C语言开源项目   - 1. Webbench Webbench是一个在linux下使用的非常简单的网站压测工具.它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工 ...

随机推荐

  1. c#用牛顿法计算根号下2的值

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  2. android studio 开启genymotion 出现"failed to create framebuffer image"

    出现错误 Unable to start the virtul device To start virtual devices, make sure that your video card supp ...

  3. 从零开始学习Node.js例子四 多页面实现数学运算 续一(使用connect和express框架)

    1.使用connect框架 .use方法用于绑定中间件到connect服务器,它会配置一系列在接到请求时调用的中间件模块,此例中我们要配置的中间件有favicon logger static rout ...

  4. Smart210学习记录------nor flash驱动

    nor flash驱动与nand flash驱动的差别不大,只是设置不同的结构体而已,, nor flash驱动代码: #include <linux/module.h> #include ...

  5. JAVA入门第二季 第一章 类和对象

    面向对象编程 Object Oriented Programming OOP 第一.什么是类和对象 在具体说明类和对象之前,先说说别的. 眼睛在人类身体上最为有用的器官.如果一个没有了眼睛,这个人与世 ...

  6. Python变量、数据类型6

    1.Python变量 变量,即代表某个value的名字. 变量的值存储在内存中,这意味着在创建变量时会在内存中开辟一个空间. !!!即值并没有保存在变量中,它们保存在计算机内存的深处,被变量引用.所以 ...

  7. 什么是FTP服务器

    FTP服务器,则是在互联网上提供存储空间的计算机,它们依照FTP协议提供服务. FTP的全称是File Transfer Protocol(文件传输协议).顾名思义,就是专门用来传输文件的协议.简单地 ...

  8. C# 多线程详解 Part.01(UI 线程、子线程)

    基本概念 什么是进程?        当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源.一个进程至少有一个主线程. 什么是线程?        线程是程序中的一 ...

  9. 【Unity3D技巧】在Unity中使用事件/委托机制(event/delegate)进行GameObject之间的通信 (二) : 引入中间层NotificationCenter

    作者:王选易,出处:http://www.cnblogs.com/neverdie/ 欢迎转载,也请保留这段声明.如果你喜欢这篇文章,请点[推荐].谢谢! 一对多的观察者模式机制有什么缺点? 想要查看 ...

  10. @ResponseBody 返回中文乱码问题解决 spingmvc

    <!-- UTF8解决乱码问题 --> <bean class="org.springframework.web.servlet.mvc.method.annotation ...