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());
}
}