用cocos2d-x 解析xml

原帖地址 http://blog.sina.com.cn/s/blog_7018d38201010yop.html

cocos2d-x如何获得Resources目录路径?--

CCFileUtils::fullPathFromRelativePath("文件名")

可以使用TinyXML

 TinyXML是一个开源的解析XML的解析库,能够用于C++,能够在WindowsLinux中编译。这个解析库的模型通过解析XML文件,然后在内存中生成DOM模型,从而让我们很方便的遍历这课XML树。
    注:DOM模型即文档对象模型,是将整个文档分成多个元素(如书、章、节、段等),并利用树型结构表示这些元素之间的顺序关系以及嵌套包含关系(理解html语言的读者会很容易理解这种树状模型)。               
    如下是一个XML片段:
    <Persons>
        <Person ID="1">
            <name>周星星</name>
            <age>20</age>
        </Person>
        <Person ID="2">
            <name>白晶晶</name>
            <age>18</age>
        </Person>
    </Persons>
    在TinyXML中,根据XML的各种元素来定义了一些类:
        TiXmlBase:整个TinyXML模型的基类。
                TiXmlAttribute:对应于XML中的元素的属性。
                TiXmlNode:对应于DOM结构中的节点。
                        TiXmlComment:对应于XML中的注释。
                        TiXmlDeclaration:对应于XML中的申明部分,即<?versiong="1.0" ?>。
                        TiXmlDocument:对应于XML的整个文档。
                        TiXmlElement:对应于XML的元素。
                        TiXmlText:对应于XML的文字部分。
                        TiXmlUnknown:对应于XML的未知部分。 
        TiXmlHandler:定义了针对XML的一些操作。
    那我们如何使用这些类以及他们的方法来操纵我们的XML呢?请看下面。
    一、读取XML(假设我们的Xml文档中的内容与上面的Xml内容一样)
    //创建一个XML的文档对象
    TiXmlDocument *myDocument = new TiXmlDocument("填上你的Xml文件名");
    myDocument->LoadFile();
    //获得根元素,即Persons。
    TiXmlElement *RootElement = myDocument.RootElement();
    //输出根元素名称,即输出Persons。
    cout << RootElement->Value() << endl;
    //获得第一个Person节点。
    TiXmlElement *FirstPerson = RootElement->FirstChildElement();
    //获得第一个Person的name节点和age节点和ID属性。
    TiXmlElement *NameElement = FirstPerson->FirstChildElement();
    TiXmlElement *AgeElement = NameElement->NextSiblingElement();
    TiXmlAttribute *IDAttribute = FirstPerson->FirstAttribute();
    //输出第一个Person的name内容,即周星星;age内容,即20;ID属性,即1。
    cout << NameElement->FirstChild()->Value << endl;
    cout << AgeElement->FirstChild()->Value << endl;
    cout << IDAttribute->Value() << endl;

    
    看,读取XML是不是很简单阿,和Java的XML解析库非常的相似,就是名字改了一下而已。
    二、生成XML内容
    //创建一个XML的文档对象。
    TiXmlDocument *myDocument = new TiXmlDocument();
    //创建一个根元素并连接。
    TiXmlElement *RootElement = new TiXmlElement("Persons");
    myDocument->LinkEndChild(RootElement);
    //创建一个Person元素并连接。
    TiXmlElement *PersonElement = new TiXmlElement("Person");
    RootElement->LinkEndChild(PersonElement);
    //设置Person元素的属性。
    PersonElement->SetAttribute("ID", "1");
    //创建name元素、age元素并连接。
    TiXmlElement *NameElement = new TiXmlElement("name");
    TiXmlElement *AgeElement = new TiXmlElement("age");
    PersonElement->LinkEndChild(NameElement);
    PersonElement->LinkEndChild(AgeElement);
    //设置name元素和age元素的内容并连接。
    TiXmlText *NameContent = new TiXmlText("周星星");
    TiXmlText *AgeContent = new TiXmlText("20");
    NameElement->LinkEndChild(NameContent);
    AgeElement->LinkEndChild(AgeContent);
    //保存到文件
    myDocument->SaveFile("要保存的xml文件名");
    这样,便创建了一个如下的xml文件:
    <Persons>
        <Person ID="1">
            <name>周星星</name>
            <age>20</age>
        </Person>
    </Persons>



tinyxml使用笔记与总结

 

在TinyXML中,根据XML的各种元素来定义了一些类:
        TiXmlBase:整个TinyXML模型的基类。
        TiXmlAttribute:对应于XML中的元素的属性。
        TiXmlNode:对应于DOM结构中的节点。
        TiXmlComment:对应于XML中的注释。
        TiXmlDeclaration:对应于XML中的申明部分,即<?versiong="1.0" ?>。
        TiXmlDocument:对应于XML的整个文档。
        TiXmlElement:对应于XML的元素。
        TiXmlText:对应于XML的文字部分。
        TiXmlUnknown:对应于XML的未知部分。 
        TiXmlHandler:定义了针对XML的一些操作。

例如:

用cocos2d-x <wbr>解析xml <? xml version="1.0" standalone=no>
用cocos2d-x <wbr>解析xml<!– Our to do list data –>
用cocos2d-x <wbr>解析xml<ToDo>
用cocos2d-x <wbr>解析xml<Item priority="1"> Go to the <bold>Toy store!</bold></Item>
用cocos2d-x <wbr>解析xml<Item priority="2"> Do bills</Item>
用cocos2d-x <wbr>解析xml</ToDo> 



整个对象树: 

TiXmlDocument "demo.xml"
TiXmlDeclaration "version=’1.0′" "standalone=no"
TiXmlComment " Our to do list data"
TiXmlElement "ToDo"
TiXmlElement "Item" Attribtutes: priority = 1
TiXmlText "Go to the "
TiXmlElement "bold"
TiXmlText "Toy store!"
TiXmlElement "Item" Attributes: priority=2
TiXmlText "Do bills" 

tinyXML中,用FirstChild"名字"时,FirstChild函数的点与要找的点必父子

句柄

想要健壮地读取一个XML文档,检查方法调用后的返回值是否为null是很重要的。一种安全的检错实现可能会产生像这样的代码: 

 

用cocos2d-x <wbr>解析xml TiXmlElement *  root  =  document.FirstChildElement(  " Document "  );
用cocos2d-x <wbr>解析xml
if  root )
用cocos2d-x <wbr>解析xml
{
用cocos2d-x <wbr>解析xmlTiXmlElement
* element = root->FirstChildElement( "Element" );
用cocos2d-x <wbr>解析xml
if element )
用cocos2d-x <wbr>解析xml
{
用cocos2d-x <wbr>解析xmlTiXmlElement
* child = element->FirstChildElement( "Child" );
用cocos2d-x <wbr>解析xml
if child )
用cocos2d-x <wbr>解析xml
{
用cocos2d-x <wbr>解析xmlTiXmlElement
* child2 = child->NextSiblingElement( "Child" );
用cocos2d-x <wbr>解析xml
if child2 )
用cocos2d-x <wbr>解析xml
{
用cocos2d-x <wbr>解析xml
// Finally do something useful. 
用cocos2d-x <wbr>解析xml



用句柄的话就不会这么冗长了,使用TiXmlHandle类,前面的代码就会变成这样: 

用cocos2d-x <wbr>解析xml TiXmlHandle docHandle(  & document );
用cocos2d-x <wbr>解析xmlTiXmlElement
*  child2  =  docHandle.FirstChild(  " Document "  ).FirstChild(  " Element "  ).Child(  " Child " 1  ).ToElement();
用cocos2d-x <wbr>解析xml
if  child2 )
用cocos2d-x <wbr>解析xml
{
用cocos2d-x <wbr>解析xml
// do something useful 
用cocos2d-x <wbr>解析xml

一、读取XML,设置节点文本
如下XML片段:

用cocos2d-x <wbr>解析xml <? xml version="1.0" encoding="UTF-8" standalone="yes"  ?>
用cocos2d-x <wbr>解析xml
< ZXML >
用cocos2d-x <wbr>解析xml    
< ZAPP >
用cocos2d-x <wbr>解析xml         
< VBS_RUNTIME_PARAMS >
用cocos2d-x <wbr>解析xml               
< BROADCAST_VERSION  info ="版本" > 8 </ BROADCAST_VERSION >
用cocos2d-x <wbr>解析xml               
< Broadcast >
用cocos2d-x <wbr>解析xml                
< FileCount  info ="资源文件个数" > 69 </ FileCount >
用cocos2d-x <wbr>解析xml                
< SOURCE_1 >
用cocos2d-x <wbr>解析xml                    
< ID  info ="图片编号" > 1 </ ID >
用cocos2d-x <wbr>解析xml                    
< Version  info ="图片版本" > 1 </ Version >
用cocos2d-x <wbr>解析xml                    
< Path  info ="图片路径" > /mnt/share/1.bmp </ Path >
用cocos2d-x <wbr>解析xml                    
< FileMode  info ="文件处理模式" > 0 </ FileMode >
用cocos2d-x <wbr>解析xml                
</ SOURCE_1 >
用cocos2d-x <wbr>解析xml                
< SOURCE_2 >
用cocos2d-x <wbr>解析xml                    
< Path  info ="图片路径" > /mnt/share/2.bmp </ Path >
用cocos2d-x <wbr>解析xml                    
< ID  info ="图片编号" > 2 </ ID >
用cocos2d-x <wbr>解析xml                    
< Version  info ="图片版本" > 1 </ Version >
用cocos2d-x <wbr>解析xml                    
< FileMode  info ="文件处理模式" > 0 </ FileMode >
用cocos2d-x <wbr>解析xml                
</ SOURCE_2 >
用cocos2d-x <wbr>解析xml                用cocos2d-x <wbr>解析xml用cocos2d-x <wbr>解析xml.
用cocos2d-x <wbr>解析xml                
</ Broadcast >
用cocos2d-x <wbr>解析xml         
</ VBS_RUNTIME_PARAMS >
用cocos2d-x <wbr>解析xml    
</ ZAPP >
用cocos2d-x <wbr>解析xml
</ ZXML >


要设置BROADCAST_VERSION节点的值 8为其他值,可参考如下代码(将值加1):
用ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )方法替换

用cocos2d-x <wbr>解析xml        TiXmlDocument doc("zapp.conf");
用cocos2d-x <wbr>解析xml    doc.LoadFile();
用cocos2d-x <wbr>解析xml    TiXmlHandle docHandle( 
& doc );
用cocos2d-x <wbr>解析xmlTiXmlElement
*  Broadcast_ver  =  docHandle.FirstChild( " ZXML " ).FirstChild( " ZAPP " ).FirstChild( " VBS_RUNTIME_PARAMS " ).FirstChildElement( " BROADCAST_VERSION " ).ToElement();
用cocos2d-x <wbr>解析xml    TiXmlNode 
*  oldnode  =   Broadcast_ver -> FirstChild();
用cocos2d-x <wbr>解析xml    
const   char   * ver  =  Broadcast_ver -> GetText();
用cocos2d-x <wbr>解析xml    
int  oldVer  =  atoi(ver);
用cocos2d-x <wbr>解析xml    CString newVer;
用cocos2d-x <wbr>解析xml    newVer.Format(
" %d " ,oldVer + 1 );
用cocos2d-x <wbr>解析xml    TiXmlText newText(newVer);
用cocos2d-x <wbr>解析xml    Broadcast_ver
-> ReplaceChild(oldnode,newText);
用cocos2d-x <wbr>解析xml    AfxMessageBox(Broadcast_ver
-> GetText()); // 输出值
用cocos2d-x <wbr>解析xml    
doc.SaveFile();

二,删除节点,属性值

RemoveChild( TiXmlNode* removeThis )方法删除父节点的子节点,
RemoveAttribute( const char * name )方法删除属性值.

例如删除BROADCAST_VERSION节点

用cocos2d-x <wbr>解析xml TiXmlHandle docHandle(  & doc );
用cocos2d-x <wbr>解析xml    TiXmlElement
*  Broadcast_ver  =  docHandle.FirstChild( " ZXML " ).FirstChild( " ZAPP " ).FirstChild( " VBS_RUNTIME_PARAMS " ).ToElement();
用cocos2d-x <wbr>解析xml
用cocos2d-x <wbr>解析xml    TiXmlNode 
*  node  =   Broadcast_ver -> FirstChild( " BROADCAST_VERSION " );
用cocos2d-x <wbr>解析xml
用cocos2d-x <wbr>解析xml    Broadcast_ver
-> RemoveChild(node);

也可以删除整个SOURCE_1节点:

用cocos2d-x <wbr>解析xml TiXmlHandle docHandle(  & doc );
用cocos2d-x <wbr>解析xml    TiXmlElement
*  Broadcast  =  docHandle.FirstChild( " ZXML " ).FirstChild( " ZAPP " ).FirstChild( " VBS_RUNTIME_PARAMS " ).FirstChild( " Broadcast " ).ToElement();
用cocos2d-x <wbr>解析xml
用cocos2d-x <wbr>解析xml    TiXmlNode 
*  node  =   Broadcast -> FirstChild( " SOURCE_1 " );
用cocos2d-x <wbr>解析xml
用cocos2d-x <wbr>解析xml    Broadcast
-> RemoveChild(node);

删除BROADCAST_VERSION的info属性:

用cocos2d-x <wbr>解析xml TiXmlHandle docHandle(  & doc );
用cocos2d-x <wbr>解析xml    TiXmlElement
*  Broadcast_ver  =  docHandle.FirstChild( " ZXML " ).FirstChild( " ZAPP " ).FirstChild( " VBS_RUNTIME_PARAMS " ).FirstChildElement( " BROADCAST_VERSION " ).ToElement();
用cocos2d-x <wbr>解析xml
用cocos2d-x <wbr>解析xml    Broadcast_ver
-> RemoveAttribute( " info " );  // 删除info

可以借助NextSiblingElement()方法实现递归删除.

三,添加节点,属性值

例如在SOURCE_3下添加BROADCAST_PID节点:

用cocos2d-x <wbr>解析xml TiXmlHandle docHandle(  & doc );
用cocos2d-x <wbr>解析xml    TiXmlElement
*  Broadcast  =  docHandle.FirstChild( " ZXML " ).FirstChild( " ZAPP " ).FirstChild( " VBS_RUNTIME_PARAMS " ).FirstChild( " Broadcast " ).ToElement();
用cocos2d-x <wbr>解析xml    TiXmlElement
*  Broadcast_Pid  =   new  TiXmlElement( " BROADCAST_PID " );
用cocos2d-x <wbr>解析xml    TiXmlText 
* text  = new  TiXmlText( " 7215 " );
用cocos2d-x <wbr>解析xml    Broadcast_Pid
-> SetAttribute( " info " , " the pid " );
用cocos2d-x <wbr>解析xml    Broadcast_Pid
-> LinkEndChild(text);
用cocos2d-x <wbr>解析xml    Broadcast
-> LinkEndChild(Broadcast_Pid);

将在SOURCE_3后添加新的节点:

用cocos2d-x <wbr>解析xml < BROADCAST_PID  info ="the pid" > 7215 </ BROADCAST_PID >

四,最后说一下中文乱码的问题

乱码是由于GB2312与UTF8之间转换不当造成的,tinyxml在处理UTF8本身没有问题,当你打开一个UTF8的文档,可以在加载的时候指定UTF8的方式,或者文档声明处指明的编码格式,tinyxml会按照相应的编码格式加载,但很多时候当我们输出或写入中文字段时会出现乱码,无论在内存,还是打印出来的内容.这是因为我们的软件通常是GB2312编码,而读取或写入的内容是UTF8,自然就会出错.可以借助网上的两个函数来实现转换(原作者不详):

用cocos2d-x <wbr>解析xml      void  ConvertUtf8ToGBK(CString &  strUtf8) 
用cocos2d-x <wbr>解析xml    
{
用cocos2d-x <wbr>解析xml        
int len=MultiByteToWideChar(CP_UTF8, 0(LPCTSTR)strUtf8, -1NULL,0);
用cocos2d-x <wbr>解析xml        unsigned 
short * wszGBK = new unsigned short[len+1];
用cocos2d-x <wbr>解析xml        memset(wszGBK, 
0len * 2 + 2);
用cocos2d-x <wbr>解析xml        MultiByteToWideChar(CP_UTF8, 
0(LPCTSTR)strUtf8, -1wszGBK, len);
用cocos2d-x <wbr>解析xml
用cocos2d-x <wbr>解析xml        len 
= WideCharToMultiByte(CP_ACP, 0wszGBK, -1NULL, 0NULL, NULL);
用cocos2d-x <wbr>解析xml        
char *szGBK=new char[len + 1];
用cocos2d-x <wbr>解析xml        memset(szGBK, 
0len + 1);
用cocos2d-x <wbr>解析xml        WideCharToMultiByte (CP_ACP, 
0wszGBK, -1szGBK, len, NULL,NULL);
用cocos2d-x <wbr>解析xml
用cocos2d-x <wbr>解析xml        strUtf8 
= szGBK;
用cocos2d-x <wbr>解析xml        delete[] szGBK;
用cocos2d-x <wbr>解析xml        delete[] wszGBK;
用cocos2d-x <wbr>解析xml    }

用cocos2d-x <wbr>解析xml
用cocos2d-x <wbr>解析xml
用cocos2d-x <wbr>解析xml    
void  ConvertGBKToUtf8(CString &  strGBK)
用cocos2d-x <wbr>解析xml    
{
用cocos2d-x <wbr>解析xml        
int len=MultiByteToWideChar(CP_ACP, 0(LPCTSTR)strGBK, -1NULL,0);
用cocos2d-x <wbr>解析xml        unsigned 
short * wszUtf8 = new unsigned short[len+1];
用cocos2d-x <wbr>解析xml        memset(wszUtf8, 
0len * 2 + 2);
用cocos2d-x <wbr>解析xml        MultiByteToWideChar(CP_ACP, 
0(LPCTSTR)strGBK, -1wszUtf8, len);
用cocos2d-x <wbr>解析xml
用cocos2d-x <wbr>解析xml        len 
= WideCharToMultiByte(CP_UTF8, 0wszUtf8, -1NULL, 0NULL, NULL);
用cocos2d-x <wbr>解析xml        
char *szUtf8=new char[len + 1];
用cocos2d-x <wbr>解析xml        memset(szUtf8, 
0len + 1);
用cocos2d-x <wbr>解析xml        WideCharToMultiByte (CP_UTF8, 
0wszUtf8, -1szUtf8, len, NULL,NULL);
用cocos2d-x <wbr>解析xml
用cocos2d-x <wbr>解析xml        strGBK 
= szUtf8;
用cocos2d-x <wbr>解析xml        delete[] szUtf8;
用cocos2d-x <wbr>解析xml        delete[] wszUtf8;
用cocos2d-x <wbr>解析xml    }

当然,你也可以用MultiByteToWideChar,WideCharToMultiByte函数自己实现转换.以上是简单应用的几个举例,理解他们,相信你已经能写出满足自己需要的代码了.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值