1,配置tinyxml2文件:加tinyxml2.cpp and tinyxml2.h.
2. 主函数 main()
#include "tinyxml2.h"
#include "Scene.h"
using namespace std;
using namespace tinyxml2;
void main()
{
XMLScene *oldScene = new XMLScene();
oldScene->ReadXML("scene.xml");
//encode
char buf[DEFAULT_BUFLEN];
int index = 0;
oldScene->EncodeAssembly(buf, index);
//decode
index = 0;
XMLScene *analyzedScene= new XMLScene();
oldScene->DecodeAssembly(buf, index, analyzedScene);
analyzedScene->WriteXML("newScene.xml");
}
#pragma once
#include <iostream>
#include <sstream>
#include <list>
#include "tinyxml2.h"
using namespace std;
using namespace tinyxml2;
// 相关字符串的长度
#define LEN_NAME 32
#define LEN_ID 32
#define LEN_ADDRESS 256
#define DEFAULT_BUFLEN 40960
enum NodeType{ NODE_SCENE, NODE_ASSEMBLY, NODE_PART };
class PartNode
{
public:
NodeType nodeType; // 节点类型
//wchar_t name[LEN_NAME]; // 节点名称
char name[LEN_NAME];
char ID[LEN_ID];
char FBX_address[LEN_ADDRESS];
double transform[3];
double rotation[3];
double scale[3];
// ModelMesh m_modelMesh;
public:
NodeType type() { return nodeType; }
void Set(const char * _name, const char * _FBX_address, double _transform[3], double _rotation[3], double _scale[3]);
inline int byte_size();
virtual void ToCharArray(char buf[], int & index);
//bool InitNode(TiXmlElement *xmlNode);
PartNode(NodeType type) : nodeType(type) {};
PartNode() : PartNode(NODE_PART) { };
PartNode(char * buf, int & index);
virtual ~PartNode();
};
class AssemblyNode : public PartNode
{
public:
list <PartNode*> parts;
list <AssemblyNode*> assemblys;
public:
AssemblyNode(char *buf, int & index);
AssemblyNode() : PartNode(NODE_ASSEMBLY) { };
};
class XMLScene
{
public:
//1.public variables
double speed, delay;
//2.assembly node
AssemblyNode *scene;
bool ReadXML(const char* file);
void WriteXML(const char* xmlPath);
void EncodeAssembly(char buf[], int& index );
void XMLScene::DecodeAssembly(char buf[], int index, XMLScene * result);
XMLScene();
~XMLScene();
private:
};
#include "Scene.h"
string doubleToString(double num)
{
char str[256];
sprintf_s(str, "%.8lf", num);
string result = str;
return result;
}
string doubleArrayToStringN(double data[], int count)
{
string temp;
for (int i = 0; i < count - 1; i++)
{
temp = temp + doubleToString(data[i]) + " ";
}
temp += doubleToString(data[count - 1]);
return temp;
}
void CharToDoubleN(double *buf, int n, const char * content)
{
stringstream ss(content);
for (int i = 0; i < n; i++)
{
ss >> *(buf + i);
}
}
/*
PartNode::PartNode(char buf[], int & index)
{
// get value of nodetype
int len = sizeof(NodeType);
memcpy_s(&nodeType, len, &buf[index], len);
index += len;
// get value of name
len = sizeof(char) * LEN_NAME;
memcpy_s(&name, len, &buf[index], len);
index += len;
// get value of type
len = sizeof(char) * LEN_ID;
memcpy_s(&ID, len, &buf[index], len);
index += len;
}
void PartNode::ToCharArray(char buf[], int &index)
{
// nodeType
int len = sizeof(NodeType);
memcpy_s(&(buf[index]), len, &nodeType, len);
index += len;
// copy byte count of the object
len = sizeof(name);
memcpy_s(&(buf[index]), len, name, len);
index += len;
copy id to buf
len = sizeof(ID);
memcpy_s(&(buf[index]), len, ID, len);
index += len;
int _type;
char _name[LEN_NAME];
char _ID[LEN_ID];
memcpy_s(&_type, sizeof(__int32), &buf[0], sizeof(__int32));
memcpy_s(&_name, sizeof(char)*LEN_NAME, &buf[sizeof(__int32)], sizeof(char)*LEN_NAME);
memcpy_s(&_ID, sizeof(char)*LEN_ID, &buf[sizeof(__int32) + sizeof(char)*LEN_NAME], sizeof(char)*LEN_ID);
}
int PartNode::base_byte_size()
{
return sizeof(__int32) + sizeof(char)* LEN_NAME + sizeof(char)*LEN_ID;
}
*/
void PartNode::Set(const char * _name, const char * _FBX_address, double _transform[3], double _rotation[3], double _scale[3])
{
strncpy_s(name, _name, LEN_NAME);
strncpy_s(FBX_address, _FBX_address, LEN_ADDRESS);
for (int i = 0; i<3;i++)
{
transform[i] = _transform[i];
rotation[i] = _rotation[i];
scale[i] = _scale[i];
}
}
// **************************************************************************************************************************
// class PartNode
// **************************************************************************************************************************
PartNode::PartNode(char *buf, int & index)
{
// get value of nodetype
int len = sizeof(NodeType);
memcpy_s(&nodeType, len, &buf[index], len);
index += len;
// get value of name
len = sizeof(char) * LEN_NAME;
memcpy_s(&name, len, &buf[index], len);
index += len;
// get value of type
len = sizeof(char) * LEN_ID;
memcpy_s(&ID, len, &buf[index], len);
index += len;
len = sizeof(FBX_address);
memcpy_s(FBX_address, len, &buf[index], len); // 拷贝零件ID
index += len;
len = sizeof(transform);
memcpy_s(transform, len, &buf[index], len); // 拷贝零件ID
index += len;
len = sizeof(rotation);
memcpy_s(rotation, len, &buf[index], len); // 拷贝零件ID
index += len;
len = sizeof(scale);
memcpy_s(scale, len, &buf[index], len); // 拷贝零件ID
index += len;
}
PartNode::~PartNode()
{
};
int PartNode::byte_size()
{
int len = sizeof(__int32) + sizeof(char)* LEN_NAME + sizeof(char)*LEN_ID;
len += LEN_ADDRESS + 3 * sizeof(double) + 3 * sizeof(double) + 3 * sizeof(double);
return len;
}
void PartNode::ToCharArray(char buf[], int & index)
{
// nodeType
int len = sizeof(NodeType);
memcpy_s(&(buf[index]), len, &nodeType, len);
index += len;
// copy byte count of the object
len = sizeof(name);
memcpy_s(&(buf[index]), len, name, len);
index += len;
copy id to buf
len = sizeof(ID);
memcpy_s(&(buf[index]), len, ID, len);
index += len;
/*
int _type;
char _name[LEN_NAME];
char _ID[LEN_ID];
memcpy_s(&_type, sizeof(__int32), &buf[0], sizeof(__int32));
memcpy_s(&_name, sizeof(char)*LEN_NAME, &buf[sizeof(__int32)], sizeof(char)*LEN_NAME);
memcpy_s(&_ID, sizeof(char)*LEN_ID, &buf[sizeof(__int32) + sizeof(char)*LEN_NAME], sizeof(char)*LEN_ID);
*/
len = LEN_ADDRESS;
memcpy_s(&(buf[index]), len, FBX_address, len);
index += len;
len = sizeof(transform);
memcpy_s(&(buf[index]), len, transform, len);
index += len;
len = sizeof(rotation);
memcpy_s(&(buf[index]), len, rotation, len);
index += len;
len = sizeof(scale);
memcpy_s(&(buf[index]), len, scale, len);
index += len;
}
// **************************************************************************************************************************
// class AssemblyNode
// **************************************************************************************************************************
AssemblyNode::AssemblyNode(char *buf, int & index) : PartNode(buf, index)
{
}
void ReadAttributes(PartNode * part, XMLElement * EleAssembly)
{
strncpy_s(part->name, EleAssembly->Attribute("name"), LEN_NAME);
strncpy_s(part->ID, EleAssembly->Attribute("ID"), LEN_NAME);
strncpy_s(part->FBX_address, EleAssembly->Attribute("FBX"), LEN_ADDRESS);
CharToDoubleN(part->transform, 3, EleAssembly->Attribute("Transform"));
CharToDoubleN(part->rotation, 3, EleAssembly->Attribute("Rotation"));
CharToDoubleN(part->scale, 3, EleAssembly->Attribute("Scale"));
}
void BrowseChildren(XMLElement* xmlParent, AssemblyNode * world)
{
XMLElement *EleAssembly = xmlParent->FirstChildElement();
while (EleAssembly != NULL) // 如果孩子节点不为空
{
if (strcmp("Part", EleAssembly->Value()) == 0)
{
PartNode *part = new PartNode();
ReadAttributes(part, EleAssembly);
/* / ***********START*************** /
char buf[DEFAULT_BUFLEN];
int index = 0;
part.ToCharArray(buf, index);
int _type;
char _name[LEN_NAME];
char _ID[LEN_ID];
memcpy_s(&_type, sizeof(__int32), &buf[0], sizeof(__int32));
memcpy_s(&_name, sizeof(char)*LEN_NAME, &buf[sizeof(__int32)], sizeof(char)*LEN_NAME);
memcpy_s(&_ID, sizeof(char)*LEN_ID, &buf[sizeof(__int32) + sizeof(char)*LEN_NAME], sizeof(char)*LEN_ID);
index = 0;
PartNode aaa(buf, index);
/ ************END************** /*/
world->parts.push_back(part);
}
else if (strcmp("Assembly", EleAssembly->Value()) == 0)
{
AssemblyNode *assembly = new AssemblyNode();
ReadAttributes(assembly, EleAssembly);
BrowseChildren(EleAssembly, assembly);
world->assemblys.push_back(assembly);
}
EleAssembly = EleAssembly->NextSiblingElement();
}
}
void EncodeChild(char buf[], int & index, AssemblyNode * world)
{
cout << "index is " << index << endl;
for (list<AssemblyNode*>::iterator it = world->assemblys.begin(); it != world->assemblys.end(); it++)
{
//1.attributes
(*it)->ToCharArray(buf, index);
//补充两个变量为装配体和零件个数,用于解析
int len = sizeof(int);
int assemblySize = (*it)->assemblys.size();
memcpy_s(&(buf[index]), len, &assemblySize, len);
index += len;
len = sizeof(int);
int partSize = (*it)->parts.size();
memcpy_s(&(buf[index]), len, &partSize, len);
index += len;
//2.parts
EncodeChild(buf, index, (*it));
}
for (list<PartNode*>::iterator it = world->parts.begin(); it != world->parts.end(); it++)
{
// count????
(*it)->ToCharArray(buf, index);
}
}
void XMLScene::EncodeAssembly(char buf[], int& index)
{
int len = sizeof(double);
memcpy_s(&(buf[index]), len, &speed, len);
index += len;
len = sizeof(double);
memcpy_s(&(buf[index]), len, &delay, len);
index += len;
scene->ToCharArray(buf, index);
//补充两个变量为装配体和零件个数,用于解析
len = sizeof(int);
int assemblySize = scene->assemblys.size();
memcpy_s(&(buf[index]), len, &assemblySize, len);
index += len;
len = sizeof(int);
int partSize = scene->parts.size();
memcpy_s(&(buf[index]), len, &partSize, len);
index += len;
EncodeChild(buf, index, scene);
}
void DecodeChild(char buf[], int & index, AssemblyNode *world)
{
int len = sizeof(int);
int assemblySize;
memcpy_s(&assemblySize, len, &(buf[index]), len);
index += len;
len = sizeof(int);
int partSize;
memcpy_s(&partSize, len, &(buf[index]), len);
index += len;
for (int i = 0; i <assemblySize; i++)
{
AssemblyNode * assembly=new AssemblyNode(buf, index);
//EncodeChild(buf, index, world.assemblys[i]);
DecodeChild(buf, index, assembly);
world->assemblys.push_back(assembly);
}
for (int i = 0; i < partSize; i++)
{
// count????
//world.parts[i].ToCharArray(buf, index);
PartNode * part=new PartNode(buf, index);
world->parts.push_back(part);
cout << "index is " << index << endl;
cout << "decode part:" << part->name << endl;
}
}
void XMLScene::DecodeAssembly(char buf[], int index, XMLScene *result)
{
int len = sizeof(speed);
memcpy_s(&result->speed, len, &(buf[index]), len);
index += len;
len = sizeof(delay);
memcpy_s(&result->delay, len, &(buf[index]), len);
index += len;
result->scene = new AssemblyNode(buf, index);
//AssemblyNode world(buf, index);
DecodeChild(buf, index, result->scene);
}
void WriteAttributes(XMLElement * ele_Part, PartNode *part)
{
ele_Part->SetAttribute("name", part->name);
ele_Part->SetAttribute("ID", part->ID);
ele_Part->SetAttribute("FBX", part->FBX_address);
ele_Part->SetAttribute("Transform", doubleArrayToStringN(part->transform, 3).c_str());
ele_Part->SetAttribute("Rotation", doubleArrayToStringN(part->rotation, 3).c_str());
ele_Part->SetAttribute("Scale", doubleArrayToStringN(part->scale, 3).c_str());
}
void WriteAssembly(XMLDocument &doc, XMLElement *ele_World, AssemblyNode *world)
{
for (list<AssemblyNode*>::iterator it = world->assemblys.begin(); it != world->assemblys.end(); it++)
{
XMLElement* ele_Assembly = doc.NewElement("Assembly");
ele_World->InsertEndChild(ele_Assembly);
WriteAttributes(ele_Assembly,*(it));
WriteAssembly(doc, ele_Assembly,*(it));
}
for (list<PartNode*>::iterator it = world->parts.begin(); it != world->parts.end(); it++)
{
XMLElement* ele_Part = doc.NewElement("Part");
ele_World->InsertEndChild(ele_Part);
WriteAttributes(ele_Part, *(it));
}
}
bool XMLScene::ReadXML(const char* file)
{
XMLDocument docR;
docR.LoadFile(file);
if (docR.Error())
{
cout << "ERROR! XML file error!" << endl;
return false;
}
docR.SaveFile("Formatted.xml");
XMLElement *ele_World = docR.RootElement();
speed = stod(ele_World->Attribute("Speed"));
delay = stod(ele_World->Attribute("Delay"));
XMLElement *ele_Scene = ele_World->FirstChildElement("Scene");
if (ele_Scene != NULL)
{
ReadAttributes(scene, ele_Scene);
BrowseChildren(ele_Scene, scene);
}
return true;
}
void XMLScene::WriteXML(const char* xmlPath)
{
FILE* fp;
fopen_s(&fp, xmlPath, "w+");//创建空xml文件
fclose(fp);
XMLDocument doc;
doc.LoadFile(xmlPath);//载入xml文件
XMLDeclaration* declaration = doc.NewDeclaration();//添加xml文件头申明
doc.InsertFirstChild(declaration);
XMLElement *Root = doc.NewElement("World");
doc.InsertEndChild(Root);
Root->SetAttribute("Speed ", doubleToString(speed).c_str());
Root->SetAttribute("Delay ", doubleToString(delay).c_str());
/*
XMLElement* ele_Speed = doc.NewElement("Speed");
XMLText* text_Speed = doc.NewText(doubleToString(speed).c_str());
ele_Speed->InsertEndChild(text_Speed);
Root->InsertEndChild(ele_Speed);
XMLElement* ele_Delay = doc.NewElement("Speed");
XMLText* text_Delay = doc.NewText(doubleToString(delay).c_str());
ele_Delay->InsertEndChild(text_Delay);
Root->InsertEndChild(ele_Delay);
*/
//insert Head
XMLElement* ele_World = doc.NewElement("Scene");
Root->InsertEndChild(ele_World);
WriteAttributes(ele_World, scene);
WriteAssembly(doc, ele_World, scene);
doc.SaveFile(xmlPath);
}
XMLScene::XMLScene()
{
scene =new AssemblyNode();
}
XMLScene::~XMLScene()
{
double scene;
}
<?xml version="1.0"?>
<!-- root name -->
<World Speed ="20.1245215500000010" Delay ="30000.0000000000000000">
<!--
Following is explaination of this scene XML defination.
1.This file is defined using a TREE structure
2.The root is world coordinate
3.Each node and child node are defined Assembly or Part. Assembly is father node of Part.
4.From root, can find every part in the scene
5.Every part has attributes, include but not limited to: position, rotation, scale, model address
How to use.
1.The TREE includes an algorithm to traverse, insert, delete, modify each node
2.Only analyzed and stored in Server, send ASCII code to Client for their sepcial requirement
3.
-->
<Scene name="Scene 1" ID ="S01" FBX="https://leg01" Transform="10 20 10" Rotation="1 2 3" Scale="1 1 1">
<!--Assembly name="room" ID="A01"-->
<Assembly name="desk" ID="A01" FBX="https://leg01" Transform="10 20 10" Rotation="1 2 3" Scale="1 1 1">
<Assembly name="desk2" ID="A02" FBX="https://leg01" Transform="10 20 10" Rotation="1 2 3" Scale="1 1 1">
<Part name="leg3" ID="P03" FBX="https://leg01" Transform="10.0000000000000000 20.0000000000000000 10.0000000000000000" Rotation="1 2 3" Scale="1 1 1"/>
<Part name="leg4" ID="P04" FBX="https://leg01" Transform="10 20 10" Rotation="1 2 3" Scale="1 1 1"/>
</Assembly>
<Part name="leg1" ID="P01" FBX="https://leg01" Transform="10 20 10" Rotation="1 2 3" Scale="1 1 1"/>
<Part name="leg2" ID="P02" FBX="https://leg01" Transform="10 20 10" Rotation="1 2 3" Scale="1 1 1"/>
</Assembly>
<Assembly name="desk2" ID="A02" FBX="https://leg01" Transform="10 20 10" Rotation="1 2 3" Scale="1 1 1">
<Part name="leg3" ID="P03" FBX="https://leg01" Transform="10 20 10" Rotation="1 2 3" Scale="1 1 1"/>
<Part name="leg4" ID="P04" FBX="https://leg01" Transform="10 20 10" Rotation="1 2 3" Scale="1 1 1"/>
</Assembly>
<Part name="leg5" ID="P05" FBX="https://leg01" Transform="10 20 10" Rotation="1 2 3" Scale="1 1 1"/>
<Part name="leg6" ID="P06" FBX="https://leg01" Transform="10 20 10" Rotation="1 2 3" Scale="1 1 1"/>
<Part name="leg9" ID="P07" FBX="https://leg01" Transform="10 20 10" Rotation="1 2 3" Scale="1 1 1"/>
</Scene>
</World>