看到c++中有解析xml,花了点时间学习了tinyxml2的使用(有些方法在tinyxml1中没有了,还好摸索出了野路子),并且写了比较通用方法方便以后再次使用,如果以后再遇到关于xml操作可以再补充方法或优化方法(就是一句话,有的懒得再写了)
tinyxml使用笔记与总结
C++:tinyxml的使用
tinyxml使用指导
使用tinyXML2 读写配置文件
TinyXml查找唯一节点及修改节点操作
tinyxml的设计结构分析
tinyxml2 下载地址
tinyxml 下载地址
用wstring和string 相互转化
使用很简单,解压后把两个文件(tinyxml2.h 和tinyxml2.cpp) 放入工程文件中,还有个xmltest.cpp放着官方用例,需要命名空间 using namespace tinyxml2;
在tinyxml2 中XMLNode中没有Type方法,知道这个节点是什么类型,在全遍历的时候很是头疼,通过我要遍历的xml来解释下我为什么头疼,官方删除了一个方法判断类型的方法,不知道为啥在tinyxml2中要删除,难道替换了更好的?
Cards.xml
<Root>
<Card>
<Cards>0X11Cards>
<Cardd>
<Cardds>0X12Cardds>
<Cardds>0X16Cardds>
<Carddss>
<hhlo>
<Cardss1>wor1Cardss1>
<Cardss1>wor2Cardss1>
<Cardss1>wor3Cardss1>
<Cardss1>wor4Cardss1>
hhlo>
Carddss>
Cardd>
<Cards>0X13Cards>
<Cards>0X14Cards>
<Cards>0X15Cards>
Card>
<Card>
<Cards>0X11,0X12,0X13,0X18Cards>
Card>
Root>
在这里我要获取Cards中0x11,tinyxml2中你可以获得XMLNode,但是要获得文本0x11,需要XMLElement,所以你要判断是否是XMLElement,是的话获得文本,是XMLNode,找下一个,因为没有Type()函数来判断
为了区分这两种类型,我在较长的测试中和看源码对于GetText()注释发现,可以用element->ToElement()->GetText() == nullptr 来判断,上源码注释图
注意红色画圈的地方,意思是这样的xml也就是返回null,所以正好符合我目前的需求
记录自己会用的xml方法或可能用到的方法,遇到后在总结补充,防止再次思考和重写
ParseXml.h
#pragma once
#include
#include
#include "tinyxml2.h"
#include
ParseXml.cpp
#include "ParseXml.h"
string ParserCardOperation(XMLNode* root, const char* nodeName, std::size_t count, vector>& allTextResult)
{
if (nullptr == root)
return "XML_ERROR_PARSING_ROOT";
XMLElement* node = nullptr;
std::size_t i = 0;
bool isFindAll = count == -1 ? true : false;
do
{
if (i == 0)
node = root->FirstChildElement(nodeName);
else
node = node->NextSiblingElement(nodeName); //返回当前元素同级的元素
if (nullptr == node)
return "XML_ERROR_PARSING_ELEMENT";
const char* text = node->ToElement()->GetText();
string str(text);
vector s;
s.push_back(str);
allTextResult.push_back(s);
i++;
} while (isFindAll || (!isFindAll && i < count));
return "XML_SUCCESS";
}
int ParserXml(const char* fileName, vector& result) {
XMLDocument xmlDoc;
XMLError tmpResult = xmlDoc.LoadFile(fileName);
if (tmpResult != XML_SUCCESS)
{
return tmpResult;
}
XMLNode* root = xmlDoc.RootElement();
ParserXmlOperation(root, false, result);
return XML_SUCCESS;
}
void ParserXmlOperation(XMLNode* node, bool flag, vector& result)
{
XMLNode* element;
if (!flag)
{
element = node->FirstChildElement();
}
else
{
element = node->NextSiblingElement();
}
if (element != nullptr)
{
if (element->ToElement()->GetText() == nullptr)
{
ParserXmlOperation(element, false, result);
}
else
{
string text(element->ToElement()->GetText());
result.push_back(text);
ParserXmlOperation(element, true, result);
}
}
else
{
if (strcmp("Root", node->Value()) != 0) {
ParserXmlOperation(node->Parent(), true, result);
}
}
}
int ParserXmlWithNodeValue(const char* fileName, map& result)
{
XMLDocument xmlDoc;
XMLError tmpResult = xmlDoc.LoadFile(fileName);
if (tmpResult != XML_SUCCESS)
{
return tmpResult;
}
XMLNode* root = xmlDoc.RootElement();
ParserXmlOperationWithNodeValue(root, false, result);
return XML_SUCCESS;
}
void ParserXmlOperationWithNodeValue(XMLNode* node, bool flag, map& result)
{
XMLNode* element;
if (!flag)
{
element = node->FirstChildElement();
}
else
{
element = node->NextSiblingElement();
}
if (element != nullptr)
{
if (element->ToElement()->GetText() == nullptr)
{
ParserXmlOperationWithNodeValue(element, false, result);
}
else
{
string text(element->ToElement()->GetText());
string keyValue = element->ToElement()->Value();
result.insert(map::value_type(keyValue, text));
ParserXmlOperationWithNodeValue(element, true, result);
}
}
else
{
if (strcmp("Root", node->Value()) != 0) {
ParserXmlOperationWithNodeValue(node->Parent(), true, result);
}
}
}
bool ParserXmlWithNodeValue(string& _str, Result& _result)
{
map rsCards;
int r = ParserXmlWithNodeValue(_str.c_str(), rsCards);
if (r != XML_SUCCESS)
{
return false;
}
map::iterator rsCardsIter = rsCards.begin();
vector parsedCards;
vector parsedCounts;
vector parsedLeftCards;
for (;rsCardsIter != rsCards.end();rsCardsIter++)
{
string keyValue = (*rsCardsIter).first;
if (keyValue == "Vesion")
{
_result.vesion = (*rsCardsIter).second;
}
else if (keyValue == "Cards")
{
ParserText((*rsCardsIter).second, ',', parsedCards);
}
else if (keyValue == "Count")
{
ParserText((*rsCardsIter).second, ',', parsedCounts);
}
else if (keyValue == "LeftCards")
{
ParserText((*rsCardsIter).second, ',', parsedLeftCards);
}
}
if (!parsedCards.empty() && !parsedCounts.empty())
{
vector::iterator countsIter = parsedCounts.begin();
for (;countsIter != parsedCounts.end();countsIter++)
{
_result.countsList.push_back((*countsIter));
}
if (parsedCounts.size() == 5)
{
uint16_t index = 0;
for (uint16_t i = 0;i < 4; i++)
{
vector tmpParsedCards;
for (uint16_t j = 0;j < parsedCounts[i];j++)
{
index = j + i * parsedCounts[i];
tmpParsedCards.push_back(parsedCards[index]);
}
_result.cards[i] = tmpParsedCards;
}
vector tmpRestedCards;
for (uint16_t z = index; z <= index + parsedCounts[4];z++)
{
tmpRestedCards.push_back(parsedCards[z]);
}
_result.restCardsList = tmpRestedCards;
}
}
if (!parsedLeftCards.empty())
{
_result.outCardsList = parsedLeftCards;
}
return true;
}
bool ParserXml(string& _str, Result& _result)
{
vector rsCards;
int r = ParserXml(_str.c_str(), rsCards);
if (r != XML_SUCCESS)
{
return false;
}
map> cards;
for (size_t i = 0;i < rsCards.size();i++)
{
vector parsedCards;
ParserText(rsCards[i], ',', parsedCards);
if (i == 0)
{
vector baiDaCardList;
baiDaCardList.push_back(parsedCards[0]);
_result.baiDaCardList = baiDaCardList;
}
else if (i == rsCards.size()-1)
{
_result.outCardsList = parsedCards;
}
else
{
_result.cards[i-1] = parsedCards;
}
}
return true;
}
Result.h
#pragma once
#include "stdafx.h"
class Result
{
public:
Result();
Result(std::vector _baiDaCardList, std::map>_cards);
virtual ~Result();
public:
std::vector baiDaCardList; //百塔牌的值
std::map> cards; //根据xml排的顺序存放配的牌
std::vector restCardsList; //剩余的牌
std::vector outCardsList; //不用的牌
std::vector countsList; //每个玩家手牌数量,剩余牌数量
string vesion; //版本
public:
void View();
void Clear();
};