轻量级TinyXml2的应用

时间:2025-02-14 09:01:13

TinyXml2库基本介绍

        TinyXML2 是 simple、small、efficient 的基于DOM (Document Object Model,文档对象模型) 的开源 C++ XML文件解析库,可以很方便地应用到现有的项目中 。目前,TinyXML1 开发已经停止,所有的开发都转移到了 TinyXML2。TinyXML2 适用于大部分 C/C++ 的项目,经得住考验,是最好的选择。较 TinyXML1 而言,TinyXML2 化繁为简,使用时只需要包含两个文件,而 TinyXML1 需要包含 6 个文件,一般生成静态链接库供项目使用。

        TinyXML2 使用了与 TinyXML1 相似的 API,并且拥有丰富的测试案例。但 TinyXML2 解析器相对 TinyXML1 在代码上是完全重写,它使用更少的内存,效率更高

        TinyXML2 无需 STL,也放弃了对 STL 支持。所有字符串查询均使用 C 风格字符串const char*来表示,省去 string 类型对象的构造,使代码更加简洁。

下载和使用

GitHub - leethomason/tinyxml2: TinyXML2 is a simple, small, efficient, C++ XML parser that can be easily integrated into other programs.

下载后只需要将将tinyxml2.h和tinyxml2.cpp引入项目即可,极为方便。

项目中使用示例

xmlHandle头文件

#pragma once

#include "TinyXml2/tinyxml2.h"
#include<string>
#include<map>

using namespace::tinyxml2;

namespace XmlHandle 
{
	int CreateXml(const char*xmlpath,const char*rootname);//创建
	int LoadXml(tinyxml2::XMLDocument&doc, const char*xmlpath);//从路径xmlpath加载
	int SaveXml(tinyxml2::XMLDocument&doc, const char*xmlpath);//保存xml文件到xmlpath
	//插入节点 可以携带属性
	XMLElement* InsertNode(tinyxml2::XMLDocument&doc, XMLElement*ParentRoot, const char*element, const char*value, const std::map<std::string, std::string>&AttributeMap = std::map<std::string, std::string>(), bool HasAttribute = false);

	//查询节点
	XMLElement* QueryNodeByName(tinyxml2::XMLDocument&doc, const char*NodeName, const char*Atttibute = nullptr, const char*AttributeValue = nullptr, bool hasAttribute = false);
	std::string QueryValueByName(XMLElement*node);
	std::string QueryAttByName(XMLElement*node,const char*attName);
	//删除节点
	int DeleteNode(tinyxml2::XMLDocument&doc, XMLElement*ParentRoot, const char*element, const char*Atttibute = nullptr, bool isAttribute = false);
	//更新节点值或属性
	XMLElement* UpdateNode(tinyxml2::XMLDocument&doc, XMLElement*Element, const char*element, const char*value, const char*Atttibute = nullptr, const char*AttributeValue = nullptr, bool HasAttribute = false);
	//序列化
	std::string DocToString(tinyxml2::XMLDocument&doc);
	//反序列化
	bool stringToDoc(const std::string&SmlStr, tinyxml2::XMLDocument&doc);

};

xmlHandle的实现文件

#include "XmlHandle.h"


int XmlHandle::CreateXml(const char*xmlpath,const char*rootname)
{
	const char*declartion = "<?xml version = \"1.0\" encoding = \"UTF-8\" ?>";
	XMLDocument doc;
	doc.Parse(declartion);//Parse an XML file from a character string. 覆盖
	XMLElement*root = doc.NewElement(rootname);//新增根节点
	doc.InsertEndChild(root);//InsertFirstChild InsertAfterChild InsertEndChild root下第一个 次于... 最后一个
	XMLError ErrorId = doc.SaveFile(xmlpath);
	return ErrorId;

}


int XmlHandle::LoadXml(XMLDocument&doc, const char*xmlpath)
{
	return doc.LoadFile(xmlpath);
}

int XmlHandle::SaveXml(tinyxml2::XMLDocument&doc, const char*xmlpath)
{
	return doc.SaveFile(xmlpath);
}

XMLElement* XmlHandle::InsertNode(tinyxml2::XMLDocument&doc, XMLElement*ParentRoot, const char*element, const char*value, const std::map<std::string, std::string>&AttributeMap, bool HasAttribute)
{
	XMLElement* Node = doc.NewElement(element);
	if (HasAttribute)
	{
		for (auto iter : AttributeMap)
		{
			Node->SetAttribute(iter.first.c_str(), iter.second.c_str());
		}
	}
	if (value != nullptr)//空则表示有子节点
	{
		Node->InsertEndChild(doc.NewText(value));
	}
	if (ParentRoot)
	{
		ParentRoot->InsertEndChild(Node);
	}
	else
	{
		doc.InsertEndChild(Node);
	}
	return  Node;
}


XMLElement* XmlHandle::QueryNodeByName(XMLDocument&doc, const char*NodeName, const char*Atttibute , const char*AttributeValue, bool hasAttribute)
{
	XMLElement*root = doc.RootElement();
	XMLElement* userNode = root->FirstChildElement(NodeName);
	while (!userNode)
	{
		if ((hasAttribute&&userNode->Attribute(Atttibute) == AttributeValue) || (!hasAttribute))
		{
			break;
		}
		userNode = userNode->NextSiblingElement();//下一个兄弟节点
	}
	return userNode;
}

std::string XmlHandle::QueryValueByName(XMLElement*node)
{
	if (node)
	{
		return node->GetText();
	}
	return std::string();
}

std::string XmlHandle::QueryAttByName(XMLElement*node, const char*attName)
{
	if (node)
	{
		return node->Attribute(attName);
	}
	return std::string();
}

int XmlHandle::DeleteNode(XMLDocument&doc, XMLElement*ParentRoot,const char*element, const char*Atttibute, bool HasAttribute)
{
	if (ParentRoot)
	{
		if (element)
		{
			ParentRoot->DeleteChild(ParentRoot->FirstChildElement(element));
		}
		if (HasAttribute)
		{
			ParentRoot->DeleteAttribute(Atttibute);
		}
		return 0;
	}
	return -1;
}

XMLElement* XmlHandle::UpdateNode(tinyxml2::XMLDocument&doc, XMLElement*Element, const char*element, const char*value, const char*Atttibute, const char*AttributeValue, bool HasAttribute)
{
	if (Element)
	{
		Element->SetText(value);
		if (HasAttribute)
		{
			Element->SetAttribute(Atttibute, AttributeValue);
		}
		return Element;
	}
	return nullptr;
}

std::string XmlHandle::DocToString(tinyxml2::XMLDocument&doc)
{
	XMLPrinter printer;
	doc.Print(&printer);
	return printer.CStr();
}


bool XmlHandle::stringToDoc(const std::string&SmlStr, tinyxml2::XMLDocument&doc)
{
	XMLError XmlErr = doc.Parse(SmlStr.c_str(), SmlStr.size());
	return XmlErr == XML_SUCCESS;
}

 xmlHandle的使用举例

void Qxmltest::TestXML()
{
	//创建
	using namespace XmlHandle;
	std::string path = QDir::currentPath().toStdString() + "/Test.xml";
	int ret = CreateXml(path.c_str(),"XmlDB");


	//增加节点
	tinyxml2:: XMLDocument doc;
	if (0 == LoadXml(doc, path.c_str()))
		//QueryNodeByName
	{
		using AttMap = std::map<std::string, std::string>;
		AttMap Attritubte;
		Attritubte.insert(std::make_pair("Name", "ZahngSan"));
		Attritubte.insert(std::make_pair("Gneder", "Men"));
		XMLElement*UserNode = InsertNode(doc, doc.RootElement(), "User", nullptr, Attritubte, true);
		if (UserNode)
		{
			InsertNode(doc,  UserNode, "hobby", "play games");
			InsertNode(doc,  UserNode, "Pet", "Dog");
			InsertNode(doc,  UserNode, "Language", "Chinese");
			InsertNode(doc,  UserNode, "height", "180");
			InsertNode(doc,  UserNode, "weight", "80");
		}

		Attritubte.clear();
		Attritubte.insert(std::make_pair("Name", "LiSi"));
		Attritubte.insert(std::make_pair("Gneder", "Men"));
		UserNode = InsertNode(doc,  doc.RootElement(), "User", nullptr, Attritubte, true);
		if (UserNode)
		{
			InsertNode(doc, UserNode, "hobby", "play ping-pang");
			InsertNode(doc, UserNode, "Pet", "Cat");
			InsertNode(doc, UserNode, "Language", "Chinese");
			InsertNode(doc, UserNode, "height", "181");

			AttMap weightAtt;
			weightAtt.insert(std::make_pair("WeightX", "Year"));
			weightAtt.insert(std::make_pair("WeightY", "WeightValue"));
			weightAtt.insert(std::make_pair("WeightZ", "UnKnown"));
 			XMLElement*WNode = InsertNode(doc,  UserNode, "weight", nullptr, weightAtt,true);
		
			AttMap att2020;
			att2020.insert(std::make_pair("Year?", "Yes"));
			att2020.insert(std::make_pair("Weight?", "No"));
			XMLElement*Node2020 = InsertNode(doc, WNode, "2020", "70", att2020, true);
			InsertNode(doc,  WNode, "2021", "73");
			InsertNode(doc,  WNode, "2022", "75");

			//修改
			UpdateNode(doc, Node2020, "2020", "69", "Weight", "Yes", true);

			//删除
			DeleteNode(doc, WNode, "2022", "WeightZ", true);
		}
		//查找
		QString Display;
		XMLElement*ZSNode =  QueryNodeByName(doc,"User","name","ZahngSan",true);
		if (ZSNode)
		{
			Display+=QString(QueryAttByName(ZSNode, "Gneder").c_str())+'\n';
		}

		QString xmlStr =QString::fromStdString(DocToString(doc));
		Display +=xmlStr;

		/*tinyxml2::XMLDocument doc2;
		if (stringToDoc(xmlStr.toStdString(), doc2))
		{
			XMLElement*ZSNode = QueryNodeByName(doc, "User", "name", "LiSi", true);
			if (ZSNode)
			{
				Display += QString(QueryAttByName(ZSNode, "Gneder").c_str()) + '\n';
			}
		}*/

		ui.textEdit_XML->setText(Display);
		SaveXml(doc,path.c_str());
	}
}