xml文件的解析

原创 2016年06月01日 18:16:03

分为两种解析方式:

方式一:sax方式解析

优点:逐行读取和解析,所以速度很快。

缺点:只能解析,不能往xml文件中写数据。


我们需要构建自己的xml解析类。这个类实现 抽象类 SaxDelegator,然后实现里面的3个纯虚函数。

——————————————————————————————————

yjh.xml文件内容:

<?xml version="1.0" encoding="UTF-8"?>
<All>
<Inform name="yjh" age="24" add="北京">
     <school>河南大学</school>
  <company>创思科技</company>
</Inform>
<Inform name="yy" age="25" add="上海">
     <school>北京大学</school>
  <company>清新科技园</company>
</Inform>
</All>

__________________________________________________________________

YjhParser.h

#ifndef YjhParser_h__
#define YjhParser_h__
#include "cocos2d.h"
using namespace cocos2d;
class YjhParser:public Ref,public SAXDelegator
{
public:
 //定义一个数组
 CC_SYNTHESIZE(ValueVector, list, List);
 std::string startElementName;//标签
 ValueMap row; //一行
public:
 //获取文件(这是两段式的写法,静态工厂设计模式)
 static YjhParser*  CreateWithXMLFile(std::string fileName);

 bool initWithXMLFile(std::string fileName);
 //实现代理的3个纯虚函数
 virtual void startElement(void *ctx, const char *name, const char **atts);

 virtual void endElement(void *ctx, const char *name);

 virtual void textHandler(void *ctx, const char *s, int len);

 
};

#endif // YjhParser_h__

________________________________________________________________ 

YjhParser.cpp

#include "YjhParser.h"

//获取解析xml文件的对象
YjhParser*  YjhParser::CreateWithXMLFile(std::string fileName)
{
 YjhParser *parse = new YjhParser;
 if (parse&&parse->initWithXMLFile(fileName)){
  
  parse->autorelease();
  return parse;
 }
 CC_SAFE_DELETE(parse);
 return nullptr;
}

//初始化函数

bool  YjhParser::initWithXMLFile(std::string fileName)
{
 SAXParser parser;
 parser.setDelegator(this);
 std::string filePath = FileUtils::getInstance()->fullPathForFilename(fileName);
 
 return parser.parse(filePath);
}


//实现代理的3个纯虚函数

//开始标签触发函数
void  YjhParser::startElement(void *ctx, const char *name, const char **atts){
 //忽略不用的字段
 CC_UNUSED_PARAM(ctx);
 startElementName = name;
 if (startElementName=="Inform")
 {
  row = ValueMap();
  for (int i = 0; atts[i];i+=2)
  {
   std::string key = (char*)atts[i];
   std::string value = (char*)atts[i+1];
   std::pair<std::string, Value> pair(key, Value(value));
   row.insert(pair);
  }
 }
}

//结束字段触发函数

void  YjhParser::endElement(void *ctx, const char *name){
 
 CC_UNUSED_PARAM(ctx);//不使用这个字段
 std::string endElementName = (char*)name;
 if (endElementName=="Inform")
 {
  //把一行的内容插入到数组中。
  list.push_back(Value(row));
 }

}

//文本内容触发函数

void  YjhParser::textHandler(void *ctx, const char *s, int len){
 CC_UNUSED_PARAM(ctx);//不使用这个字段

 //内容
 std::string content = std::string((char*)s, 0, len);
 std::pair<std::string, Value> pair(startElementName, Value(content));
 row.insert(pair);
}

__________________________________________________________________

YjhParserLayer.h

#ifndef YjhParserLayer_h__
#define YjhParserLayer_h__
#include "cocos2d.h"
#include "YjhParser.h" //自己实现的解析类
USING_NS_CC;
class YjhParserLayer:public Layer
{
public:
 static Scene* createScene();
 virtual bool init();
 CREATE_FUNC(YjhParserLayer);
public:
 //回调函数
 void callBack(Ref* pSender);
};

#endif // YjhParserLayer_h__

__________________________________________________________________

YjhParserLayer.cpp

#include "YjhParserLayer.h"
#include "MyUtility.h"

Scene* YjhParserLayer::createScene()
{
 auto scene = Scene::create();
 auto layer = YjhParserLayer::create();
 scene->addChild(layer);
 return scene;
}
bool YjhParserLayer::init()
{
 if (!Layer::init()){
  return false;
 }
 //创建一个按钮
 MenuItemImage *item = MenuItemImage::create("1.png", "2.png", CC_CALLBACK_1(YjhParserLayer::callBack,this));
 item->setPosition(Vec2(200, 200));
 Menu *menu = Menu::create(item, nullptr);
 menu->setAnchorPoint(Vec2::ZERO);
 menu->setPosition(Vec2::ZERO);
 this->addChild(menu);

 return true;
}

void YjhParserLayer::callBack(Ref* pSender)
{
 CCLOG("%s", MyUtility::gbk_2_utf8("Sax方式解析开始").c_str());
 //
  auto parser= YjhParser::CreateWithXMLFile("yjh.xml");
 ValueVector xmlVector= parser->getList();
 //遍历数组
 for (auto item:xmlVector){
  ValueMap row = item.asValueMap();
  //遍历字典
  for (auto dict:row)
  {
   log("%s=%s", dict.first.c_str(), dict.second.asString().c_str());
  }
 }

}

___________________

结果:

——————————————————————————————————————

网上的一些好的写法。


#pragma once
#include <string>
#include "cocos2d.h"
  
class XMLParser : public cocos2d::Ref, public cocos2d::SAXDelegator
{
public:
    staticXMLParser* parseWithFile(constchar*xmlFileName);
  
    staticXMLParser* parseWithString(constchar*content);
  
    XMLParser();
    virtual ~XMLParser();
 
    //从本地xml文件读取
    bool initWithFile(constchar*xmlFileName);
    //从字符中读取,可用于读取网络中的xml数据
    bool initWithString(constchar*content);
     
    //对应xml标签开始,如:<string name="app_name">
    virtualvoidstartElement(void*ctx,const char*name, constchar**atts);
      
    //对应xml标签结束,如:</string>
    virtualvoidendElement(void*ctx,const char*name);
  
    //对应xml标签文本
    virtualvoidtextHandler(void*ctx,const char*s, intlen);
  
    cocos2d::CCString* getString(constchar*key);
  
private:
    cocos2d::CCDictionary *m_pDictionary;
    std::string m_key;
  
    std::string startXMLElement;
    std::string endXMLElement; 
  
};

#include "XMLParser.h"
 
using namespace std;
using namespace cocos2d;
 
//字符ascii码
// 空格
const static int SPACE =32;
// 换行
const static int NEXTLINE =10;
// tab 横向制表符
const static int TAB =9;
 
XMLParser* XMLParser::parseWithFile(constchar*xmlFileName)
{
    XMLParser *pXMLParser =newXMLParser();
    if( pXMLParser->initWithFile(xmlFileName) )
    {
        pXMLParser->autorelease();  
        returnpXMLParser;
    }
    CC_SAFE_DELETE(pXMLParser);
    returnNULL;
}
 
bool XMLParser::initWithFile(constchar*xmlFileName)
{
    m_pDictionary =newCCDictionary();
    SAXParser _parser;
    _parser.setDelegator(this);
    //获取文件全路径
    string fullPath = FileUtils::getInstance()->fullPathForFilename(xmlFileName);
    CCLog("xml parser full path : %s",fullPath.c_str());
 
    return_parser.parse(fullPath);
}
 
XMLParser* XMLParser::parseWithString(constchar*content)
{
    XMLParser *pXMLParser =newXMLParser();
    if( pXMLParser->initWithString(content) )
    {
        pXMLParser->autorelease();  
        returnpXMLParser;
    }
    CC_SAFE_DELETE(pXMLParser);
    returnNULL;
}
 
bool XMLParser::initWithString(constchar*content)
{
    m_pDictionary =newCCDictionary();
    SAXParser _parse;
    _parse.setDelegator(this);
    return_parse.parse(content, strlen(content) );
}
 
//开始一个节点
// 比如<string name="app_name">小黄人大作战</string>
//name    为     :string
//atts[0] 为属性   : name
//atts[1] 为值        : app_name
//atts[2] 以此类推
void XMLParser::startElement(void *ctx, const char*name,const char**atts)
{
    this->startXMLElement = (char*)name;
    CCLog("start=%s", startXMLElement.c_str());//name
 
    if(this->startXMLElement =="string")
    {
        while(atts && *atts)
        {
            CCLog("attrs0=%s", atts[0]);   //atts[0] : name
            CCLog("attrs1=%s", atts[1]);   //atts[1] : app_name
 
            constchar*attsKey = *atts;   
            if(0== strcmp(attsKey,"name"))
            {
                ++ atts;
                constchar*attsValue = *atts;
                m_key = attsValue;         //key
                break;
            }
            ++ atts;
        }
 
    }
 
}
 
void XMLParser::endElement(void *ctx, const char*name)
{
    this->endXMLElement = (char*)name;
    CCLog("end=%s", endXMLElement.c_str());
}
 
void XMLParser::textHandler(void *ctx, const char*s,int len)
{
    string value((char*)s,0, len);
 
    //是否全是非正常字符
    bool noValue =true;
    for(inti =0; i < len; ++i)
    {
        if(s[i] != SPACE && s[i] != NEXTLINE && s[i] != TAB)
        {
            noValue =false;   
            break;
        }
    }
    if(noValue)return;
    String *pString = String::create(value);
    CCLog("key=%s value=%s", m_key.c_str(), pString->getCString());
    this->m_pDictionary->setObject(pString,this->m_key);
}
 
String* XMLParser::getString(constchar*key)
{
    string strKey(key);
    return(String *)this->m_pDictionary->objectForKey(strKey);
}
 
XMLParser::XMLParser()
{
}
 
XMLParser::~XMLParser()
{
    CC_SAFE_DELETE(this->m_pDictionary);
}



第二种解析方式:Dom解析方式

首先认识dom模型:

注意它有4类节点:

1.文档节点;

2.标记节点;

3.属性节点;

4.根节点;

通过文档节点获取根节点,通过根节点获得子节点,通过子节点获取子节点的属性节点。

层层递推的方式。

在这里有些需要注意的东西就是,实现方式的区别,Dom解析是将dom文档转换为字符串,保存到内存中,然后进行解析。

在做这个实验的时候,出错的地方很多。

但是最主要的是不要忘记引入tinyxml2.h文件,添加该库文件的搜索路径,然后就是解析函数的编写问题了。




版权声明:本文为博主原创文章,未经博主允许不得转载。

xml文件的解析

分为两种解析方式: 方式一:sax方式解析 优点:逐行读取和解析,所以速度很快。 缺点:只能解析,不能往xml文件中写数据。 我们需要构建自己的xml解析类。这个类实现 抽象类 SaxDelega...
  • yjhdxflqm
  • yjhdxflqm
  • 2016年06月01日 18:16
  • 598

解析XML文件

参考:http://blog.csdn.net/cai_xingyun/article/details/18225427 在PL/SQL中利用XML ,Oracle提供了几个组件,让开发人员能轻...
  • zhanzhib
  • zhanzhib
  • 2016年12月27日 17:27
  • 393

简单看Spring源码--对xml文件解析

Spring如何解析xml配置文件? xml配置文件是Spring中极其重要的一部分,让我们一起看一下spring解析xml文件的。...
  • nihaogeyunyun
  • nihaogeyunyun
  • 2017年04月05日 21:51
  • 620

xml基础及其解析xml文档

xml基础及其解析xml文档xml基础及其解析xml文档 xml基础语法 中国特色乱码问题 写xml文件的工具 xml中使用的转义字符 处理指令已经过时 xml的两个重要的功能 xml注释 xml解析...
  • jpzhu16
  • jpzhu16
  • 2016年06月11日 22:09
  • 8137

xml文件解析基础和签名

本文是工作中常需要用到的xml文件的处理方法以及对xml文件进行签名
  • a769901686
  • a769901686
  • 2015年05月13日 21:23
  • 1000

使用Libxml2解析xml

       今天介绍的方法为使用Dom树解析,将给出两个  实例,说明如何使用Libxml2遍历xml...
  • xjtuse_mal
  • xjtuse_mal
  • 2007年05月08日 20:39
  • 2802

xml文件四中解析方式

XML现在已经成为一种通用的数据交换格式,平台的无关性使得很多场合都需要用到XML。小编将将简单介绍一下Java解析XML的四中方法。       基本的解析方式有两种,一种叫DOM,另一种叫SAX。...
  • u013036274
  • u013036274
  • 2016年09月11日 22:03
  • 1117

android Studio 解析assets下xml文件并解析

android Studio 解析assets下xml文件并解析: language.xml Language cat="it">       lan id="1">       ...
  • bysjlwdx
  • bysjlwdx
  • 2017年11月02日 13:41
  • 255

Android XML布局文件解析过程源码解析

`mLayoutInflater.inflate(layoutResID, mContentParent)`。这行代码的作用是将我们的activity_main.xml填充到mContentParen...
  • qq_17250009
  • qq_17250009
  • 2016年08月22日 09:47
  • 3536

Cocos2dx利用CCSAXParser解析XML数据

Cocos2dx利用CCSAXParser解析XML数据 1.、准备素材(xml文件) testExcel.xml 1000娃哈哈82.34000himitrue 2.实现代码: ...
  • my183100521
  • my183100521
  • 2013年11月09日 17:14
  • 2523
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:xml文件的解析
举报原因:
原因补充:

(最多只允许输入30个字)