天天看点

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>