tinyxml非常好的实例 --c++解析XML

首先要加载头文件 和 库 

#include "..\\TinyXml\\TinyXml.h"
using namespace TinyXml;

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

这个例子对于只想简单使用xml的用户来说,非常有学习价值。 

完整程序代码:(相信具有基本C++知识的人可以明白的)

view plainprint?
#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分配出来的数组空间  
  
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(); // 找出下一个Resum  
    }  
  
    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 );  
  
            }  
        }  
    }  
  
    while (true)  
    {  
    }  
  
}  
 
xml文件内容:
<?xml version="1.0" encoding="gb2312" standalone="yes" ?>
- <resumes num="2">
- <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>


 

程序结果:

 

 评论这张

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值