山伏札记[1]

   这段日子一直没来,blog长了不少草,没办法,填几块山石吧。 sims2-lrg

   山伏就是修行者,不少都是在野的浪人之辈,我目前就仍然是这个状态。假期里放松不少,技术上面,csdn上赚分捡漏折腾了1周就没能继续,经验不足知识不够,于是SDL学了一点入门基础,看书学了学lua的用法跟一些trick,数据结构方面再看了点基础的,被推荐了解了一下TinyXml这个轻巧的库(文末就是一篇我的TinyXml入门总结)。

   换了电脑就尝试了几个新游戏,刺客信条,杀手47 血钱,重新回味一下Sims2,Portal,也是很有意思,为了玩游戏,我把预装的vista换成了xp,个人觉的还是挺值得,这也反应了vista在兼容性方面的失败。

   假期看了乱七八糟的一些闲书,看穿了50集新版射雕,郭靖的成才是靠很好的RP加上一个很好的老婆。因为两者缺一,所以我还是有待成才。大四开学就要奔忙各处找到自己向往的工作了。

   网上一个做游戏服务端的朋友教导我了解一下TinyXml这个库,并且让我写个tutorial总结一下,那么我就拿找工作的信息说事了。

———————-TinyXml简单应用————————-

   下面这些内容,就是csdn的一个人才招聘发布的RSS聚合信息,http://job.csdn.net/Con001_ProjectManage/Job/jobListRss.aspx,它使用的是RSS2.0标准,以xml的形式保存了网站和各个条目信息。(基于XML的RSS聚合可以方便的使用阅读器接收与更新,这种方式可以快速获取信息,避免了广告。xml的格式在游戏开发中也作为游戏的配置文件存在,.net工程中的app.config等配置文件也是xml格式,可见它的用处广泛,它比ini等其它格式有着更多优势,这里就不再多说。)

<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">
  <channel>
    <title>CSDN → 人才频道 → 最新职位列表</title>
    <link>http://job.csdn.net/Con001_ProjectManage/Job/JobList.Aspx</link>
    <description>CSDN → 人才频道 → 最新职位列表</description>
    <language>zh-CN</language>
    <generator>WWW.CSDN.NET</generator>
    <image>
      <title>www.csdn.net</title>
      <url>http://job.csdn.net/Images/logo_csdn_s.gif</url>
      <link>http://job.csdn.net</link>
    </image>
    <copyright>Copyright 1998 - 2005 CSDN.NET Inc. All Rights Reserved</copyright>
    <item>
      <title>软件工程师</title>
      <link>http://job.csdn.net/Jobs/ViewJob/3bc489d929b34a49bbb811dc3251a55c.aspx</link>
      <author>北京紫光北美科技开发有限公司</author>
      <guid>http://job.csdn.net/Jobs/ViewJob/3bc489d929b34a49bbb811dc3251a55c.aspx</guid>
      <pubDate>Wed, 06 Aug 2008 13:04:41 GMT</pubDate>
      <slash:comments>0</slash:comments>
      <source url="http://job.csdn.net/Jobs/ViewCompany/761f6c3a48574181991242d70a452446.aspx">北京紫光北美科技开发有限公司</source>
      <description>软件工程师</description>
    </item>
    <item>
      <title>Java 研发工程师</title>
      <link>http://job.csdn.net/Jobs/ViewJob/8fc4fa80080843098fbf882f16a89c84.aspx</link>
      <author>北京互维联创信息技术有限公司</author>
      <guid>http://job.csdn.net/Jobs/ViewJob/8fc4fa80080843098fbf882f16a89c84.aspx</guid>
      <pubDate>Wed, 06 Aug 2008 12:53:05 GMT</pubDate>
      <slash:comments>0</slash:comments>
      <source url="http://job.csdn.net/Jobs/ViewCompany/616fdfe34d7949c1b9679d37ea3f66d3.aspx">北京互维联创信息技术有限公司</source>
      <description>Java 研发工程师</description>
    </item>
    <item>
      <title>C++ 高级软件工程师</title>
      <link>http://job.csdn.net/Jobs/ViewJob/132d5d81285e41a286baea9de6b4c408.aspx</link>
      <author>北京互维联创信息技术有限公司</author>
      <guid>http://job.csdn.net/Jobs/ViewJob/132d5d81285e41a286baea9de6b4c408.aspx</guid>
      <pubDate>Wed, 06 Aug 2008 12:53:05 GMT</pubDate>
      <slash:comments>0</slash:comments>
      <source url="http://job.csdn.net/Jobs/ViewCompany/616fdfe34d7949c1b9679d37ea3f66d3.aspx">北京互维联创信息技术有限公司</source>
      <description>C++ 高级软件工程师</description>
    </item>
  </channel>
</rss>

 

xml

   xml结构保存的信息可以当作一棵树,它有且仅有一个根,这个例子中根是rss,这个例子中的这棵树如左图所示(点击可放大)。

   可以看出这个xml结构一共有四层,这里我们比较关注的信息在(红色标记的)item节点中。

   现在我们假设本地已经存在了”job.xml”这个文件,内容结构就是之前介绍的这般。

   使用TinyXml来操作xml数据就有如在xml的树形结构中游走,首先创建TiXmlDocument对象打开xml文件,这时可以使用该对象的FirstChild方法获得头结点对象,从这个头结点开始,你可以继续得到它的所有子节点,孙子节点,从一个节点可以很方便的访问它的同胞兄弟们,

   任务1.使用TinyXml遍历所有Item。

//#define TIXML_USE_STL 如果使用这个宏,tinyxml会支持一些c++的io流操作,还会使用std::string作为内建的字符串类。
#include "tinyxml.h"
#include <iostream>
using namespace std;
int main()
{
    //读文件
    TiXmlDocument *doc = new TiXmlDocument("job.xml");
    doc->LoadFile();
    if(doc->Error())
    {
        cout<<"Load file Error"<<endl;
        return -1;
    }
    //开始游走,也可以通过doc->RootElement()方法返回一个TiXmlElement指针。
    TiXmlNode* rss = doc->FirstChild("rss");
    if(rss == NULL)
    {
        cout<<"Walking on <rss> Error"<<endl;
        return -1;
    }
    TiXmlNode* channel = rss->FirstChild("channel");
    if(rss == NULL)
    {
        cout<<"Walking on <channel> Error"<<endl;
        return -1;
    }
    TiXmlElement* item = channel->FirstChildElement("item");
    if(item == NULL)
    {
        cout<<"Walking on <item> Error"<<endl;
        return -1;
    }
    //成功游走到首个item节点
    int count = 0;
    //遍历所有item
    for(TiXmlElement* elem = item;elem!= NULL;elem = elem->NextSiblingElement())
    {
        //elem就是每一个item节点
        //print(elem);
        count++;
    }
    cout<<count<<" item(s)"<<endl;
    delete doc;
}

  

任务2.打印Item数据

这里实现了print函数,接收一个Xml元素对象指针,可以理解为这个指针目前就走到了这个item上。

for循环中遍历了item节点的所有子节点

TiXmlElement::Value()获得当前节点的节点键值,TiXmlElement::GetText()获得当前节点的文本描述(注意,这个函数在没有文本描述时可能会返回NULL,这时执行类似cout<<TiXmlElement::GetText()这样的代码就会发生运行时错误),vc++里没有内置对UTF8编码打印的支持,这里的UTF8toGB使用的是我修改自VCKBASE的一个UTF8和GB2312码转换的函数,有兴趣可以查看VCKBASE的链接,对于UTF8与默认编码转换的内容可以查看wikipedia相关链接demo1

const char * UTF8toGB(const char * utf)
{
    static string temp;
    GB2312Helper::UTF_8ToGB2312(temp,utf,strlen(utf));
    return temp.c_str();
}
void print(TiXmlElement * item)
{
    for(TiXmlElement* elem = item->FirstChildElement();elem!= NULL;elem = elem->NextSiblingElement())
    {
        cout<<elem->Value()<<":"<<UTF8toGB(elem->GetText())<<endl;
    }
}

 

   执行结果如图所示。

   TiXmlElement::FirstChildElement();

   FirstChild这类函数有一个参数为const char*的重载版本,可以方便的找到某个指定键值的节点,NextSibling系列函数也是同样道理,所以也是方便应用的。请读者自行实践

任务3,获取Item中source节点的url属性。

   可以看到,程序的在打印source节点信息的时候打印了它的键值和文本,但是url这个属性没有打印出来,使用如下方法可以将其打印出来。

   只要把打印函数加上如下部分,就可以列举所有的节点的属性值。image执行结果在右边。

void print(TiXmlElement * item)
{
    for(TiXmlElement* elem = item->FirstChildElement();elem!= NULL;elem = elem->NextSiblingElement())
    {
        cout<<elem->Value()<<":"<<UTF8toGB(elem->GetText())<<endl;
        for(TiXmlAttribute* attr = elem->FirstAttribute();attr!=NULL;attr=attr->Next())
        {
            cout<<elem->Value()<<" "<<attr->Name()<<":"<<attr->Value()<<endl;
        }
    }
}

 

   这种方法判断节点是否名为source,如果是source,打印属性url,注意这个Attribute如果找不到属性也会return NULL的。Attribute这类函数也有不少个,有兴趣都可以看看。

void print(TiXmlElement * item)
{
    for(TiXmlElement* elem = item->FirstChildElement();elem!= NULL;elem = elem->NextSiblingElement())
    {
        cout<<elem->Value()<<":"<<UTF8toGB(elem->GetText())<<endl;
        if(0 == strcmp(elem->Value(),"source"))
        {
            cout<<elem->Value()<<" url:"<<elem->Attribute("url")<<endl;
        }
    }
}

   到了这里我的TinyXml介绍结束了,这里只介绍了读取信息的一些最基础的方法,至于修改,创建,插入节点也都是同样原理,实际上就是一步一步在这个树上做着操作。了解了它的类的结构关系,在进一步实践中,你将会得到更多的心得体会。我文字写得拙劣,还请各位朋友多提意见,相互交流。

关于TinyXml有用的链接

This entry was posted in other. Bookmark the permalink.

6 Responses to 山伏札记[1]

  1. foxtail says:

    哈哈TinyXML用的很广泛,我看过很多编辑器 像codeblocks 都用这个的。

    你文章排版花了不少心思吧。

  2. Gohan says:

    @foxtail
    呵呵,TinyXML比较简单易用吧:)。文章排的有点乱,我用live writer弄的,那个树状图画的有点麻烦。

  3. blankyao says:

    好久不见了啊

  4. Gohan says:

    @blankyao
    呵呵,你好,你们开学了吗?

  5. Leewings says:

    刺客信条…..
    看了宣传片,超清晰,超想玩!!!!

  6. Gohan says:

    @Leewings
    呵呵,感觉游戏有点夸张,没见过这么明目张胆的刺客。。hitman在这方面好一些

Leave a Reply