天天看點

c++用tinyxml2讀xml檔案,轉化為位元組碼,解析并儲存

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>