xml文件的解析
来源:互联网 发布:怎么阻止软件自动更新 编辑:程序博客网 时间:2024/04/29 14:56
分为两种解析方式:
方式一: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
:
static
XMLParser* parseWithFile(
const
char
*xmlFileName);
static
XMLParser* parseWithString(
const
char
*content);
XMLParser();
virtual ~XMLParser();
//从本地xml文件读取
bool initWithFile(
const
char
*xmlFileName);
//从字符中读取,可用于读取网络中的xml数据
bool initWithString(
const
char
*content);
//对应xml标签开始,如:<string name="app_name">
virtual
void
startElement(
void
*ctx,
const
char
*name,
const
char
**atts);
//对应xml标签结束,如:</string>
virtual
void
endElement(
void
*ctx,
const
char
*name);
//对应xml标签文本
virtual
void
textHandler(
void
*ctx,
const
char
*s,
int
len);
cocos2d::CCString* getString(
const
char
*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(
const
char
*xmlFileName)
{
XMLParser *pXMLParser =
new
XMLParser();
if
( pXMLParser->initWithFile(xmlFileName) )
{
pXMLParser->autorelease();
return
pXMLParser;
}
CC_SAFE_DELETE(pXMLParser);
return
NULL;
}
bool XMLParser::initWithFile(
const
char
*xmlFileName)
{
m_pDictionary =
new
CCDictionary();
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(
const
char
*content)
{
XMLParser *pXMLParser =
new
XMLParser();
if
( pXMLParser->initWithString(content) )
{
pXMLParser->autorelease();
return
pXMLParser;
}
CC_SAFE_DELETE(pXMLParser);
return
NULL;
}
bool XMLParser::initWithString(
const
char
*content)
{
m_pDictionary =
new
CCDictionary();
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
const
char
*attsKey = *atts;
if
(
0
== strcmp(attsKey,
"name"
))
{
++ atts;
const
char
*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
(
int
i =
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(
const
char
*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文件的解析
- XML文件的解析
- XML文件的解析
- xml文件的解析
- xml文件的解析
- XML文件的解析
- XML文件的解析
- XML文件的解析
- xml文件的解析
- xml文件的解析
- XML文件的解析
- xml文件的解析
- XML 文件的解析
- XML文件的解析
- xml文件的解析
- xml文件的解析
- XML文件的解析
- xml文件的sax解析
- 重新创建Activity
- appium 环境搭建
- Java设计模式(十一):外观模式(门面模式)Facade
- JS实现一个简单的抽奖系统
- DB2中错误代码池
- xml文件的解析
- iOS开发中的手势总结
- 再理解RankNet算法
- java操作excell工具类
- 自定义键盘
- Linux上查看造成IO高负载的进程
- Makefile自动编译目录下的所有.C文件
- 高德地图地址经纬度转化 URL
- Android入门:Activity四种启动模式:standard、singleTop、singleTask、singleInstance