XML文件解析库 - tinyxml2 的基础使用方法笔记
感谢MenAngel大佬的分享:TinyXml2的详解及使用 - MenAngel - 博客园 (cnblogs.com)
以下笔记主要参考的就是大佬的这篇文章。
一、我的笔记
1.使用须知
进行项目时需要tinyxml2.h
和tinyxml2.cpp
参与进来,xmltest.cpp
是官方测试(学习)文件。开源地址
编译命令 g++ -g -std=c++17 -LD:\workspace\C++\XMLFileModifier main.cpp tinyxml2.cpp -o test
-g
:这是用于生成调试信息的选项。当你在编译时包含-g
选项时,编译器将生成与源代码行号、变量名等相关的调试信息,以便你可以在调试时查看程序的内部状态。这对于在调试器中跟踪和修复代码中的问题非常有用。(编译好的可执行文件体积会变大)
-L
:这是用于指定库文件搜索路径的选项。在命令中,-LD\wor...
指定了编译器应该在D\wor...
目录中搜索库文件(找tinyxml2.h
文件)。
2.常用操作
1)生成XML文件
#include "tinyxml2.h"
#include <iostream>
using namespace tinyxml2;
int main() {
// 创建XML文档
XMLDocument doc; // XMLDocument 文档节点
// 添加XML声明节点
XMLDeclaration* decl = doc.NewDeclaration("xml version=\"1.0\" encoding=\"UTF-8\""); // XMLDeclaration
doc.InsertFirstChild(decl); // InsertFirstChild是用于向一个元素节点(XMLElement)添加子节点的函数,插入为父元素节点的第一个子节点
// 创建根元素节点
XMLElement* root = doc.NewElement("root"); // XMLElement 元素节点
doc.InsertEndChild(root); // InsertEndChild:这个函数将一个节点插入为父元素节点的最后一个子节点
// 创建元素节点 "person" 并添加到根元素
XMLElement* personElement = doc.NewElement("person");
root->InsertEndChild(personElement);
// 创建属性节点 "name" 并添加到 "person" 元素
personElement->SetAttribute("name", "John"); // 属性节点
// 创建文本节点并添加文本内容到 "person" 元素
XMLText* textElement = doc.NewText("This is some text."); // XMLText 文本节点
personElement->InsertEndChild(textElement);
// personElement->SetText("This is some text.aaaa"); // 也可以这样添加文本节点
// 创建第二个元素节点 "person" 并添加到根元素
XMLElement* personElement2 = doc.NewElement("person");
root->InsertEndChild(personElement2);
personElement2->SetAttribute("name", "anna");
// 创建第三个元素节点 "sonPerson" 并添加到第二个person元素
XMLElement* son = doc.NewElement("sonPerson");
personElement2->InsertEndChild(son);
son->SetAttribute("name","2333");
XMLText* te = doc.NewText("51555");
son->InsertEndChild(te);
// 保存XML文档到文件
doc.SaveFile("example.xml");
std::cout << "XML document created and saved to 'example.xml'" << std::endl;
return 0;
}
这是生成的XML文件
<?xml version="1.0" encoding="UTF-8"?>
<root>
<person name="John">This is some text.</person>
<person name="anna">
<sonPerson name="2333">51555</sonPerson>
</person>
</root>
2)读取&修改XML文件
#include "tinyxml2.h"
#include <iostream>
using namespace tinyxml2;
int main() {
// 创建XML文档
XMLDocument doc;
// 加载XML文件
XMLError loadResult = doc.LoadFile("D:\\Temp\\WorkSpace\\C++\\example.xml");
// 检查加载操作是否成功
if (loadResult == XML_SUCCESS) {
std::cout << "XML document loaded successfully." << std::endl;
}else{
// 如果加载操作失败,输出错误信息
std::cout << "Failed to load XML document. Error code: " << loadResult << std::endl;
return -1;
}
// 获取根元素
// FirstChildElement("root") 是 tinyXML2 中的一个函数调用,查找当前元素的子元素中第一个具有指定名称的元素,如果有多个同名的子元素,将返回第一个匹配的元素;一个都找不到就返回空指针(nullptr)。
// NextSiblingElement(const char* name) 查找当前元素的兄弟元素(下一个兄弟元素)中的第一个具有指定名称的元素。(用于在当前元素的同级元素中查找指定名称的元素,而不是在子元素中查找。)
// LastChildElement(const char* name) 查找当前元素的子元素中的最后一个具有指定名称的元素。(与 FirstChildElement 类似,但它返回匹配名称的最后一个子元素。)
XMLElement* root = doc.FirstChildElement("root");
if (!root) {
std::cout << "Root element 'root' not found in the XML document." << std::endl;
return -1;
}
// 遍历 "person" 元素
// root->FirstChildElement("person") 是 TinyXML2 提供的函数调用,它的作用是在当前元素(root)的子元素中查找名为 "person" 的第一个元素。
// 如果找到,返回该元素的指针;如果没有找到,返回空指针。当返回personElement为空时,循环结束。这是for的典型用法。
for (XMLElement* personElement = root->FirstChildElement("person"); personElement; personElement = personElement->NextSiblingElement("person")) {
const char* name = personElement->Attribute("name"); // Attribute("name") 获取名为 "name" 的属性的值。如果属性不存在,它会返回空指针(nullptr)。
const char* text = personElement->GetText(); // GetText()获取当前元素的文本内容。如果没有文本内容,它会返回空指针。
if (name) {
std::cout << "Name: " << name << std::endl;
}
if (text) {
std::cout << "Text: " << text << std::endl;
}
personElement->SetAttribute("name","xiaoming"); // 修改
personElement->SetText("100010111010100");
}
doc.SaveFile("examples.xml"); // 保存文件
return 0;
}
3)读取未知xml文件
#include "tinyxml2.h"
#include <iostream>
using namespace tinyxml2;
int main() {
// 创建XML文档
XMLDocument doc;
// 加载XML文件
XMLError loadResult = doc.LoadFile("D:\\Temp\\WorkSpace\\C++\\example.xml");
// 检查加载操作是否成功
if (loadResult != XML_SUCCESS) {
return -1;
}
// RootElement(): 这是用于获取XML文档的根元素的方法。它返回XMLDocument的根元素,通常是XML文件的最顶层元素。
XMLElement* root = doc.RootElement();
if (root) {
// 遍历整个 XML 结构
// NextSiblingElement() 函数用于获取同一层级的下一个元素
// FirstChildElement(): 该方法用于获取当前元素的第一个子元素,而不需要指定名称。
for (XMLElement* element = root->FirstChildElement(); element; element = element->NextSiblingElement()) {
// 获取元素名称
const char* elementName = element->Name();
std::cout << "Element Name: " << elementName << std::endl;
// 遍历元素的属性
for (const XMLAttribute* attr = element->FirstAttribute(); attr; attr = attr->Next()) {
const char* attrName = attr->Name();
const char* attrValue = attr->Value();
std::cout << "Attribute: " << attrName << " = " << attrValue << std::endl;
}
// 获取元素的文本内容
const char* text = element->GetText();
if (text) {
std::cout << "Text: " << text << std::endl;
}
std::cout << std::endl;
}
} else {
std::cout << "Root element not found in the XML document." << std::endl;
}
return 0;
}
注:
RootElement()
: 用于获取XML文档的根元素,可以不指定元素名称。
NextSiblingElement()
: 用于获取当前元素的下一个兄弟元素,可以不指定名称,只是返回同一层级下的下一个兄弟元素。
PreviousSiblingElement()
: 用于获取同一层级的前一个兄弟元素,可以不指定名称
FirstChildElement()
: 用于获取当前元素的第一个子元素,可以不指定名称。
LastChildElement()
: 用于获取当前元素的最后一个子元素,可以不指定名称。
Parent()
: 用于获取当前元素的父元素。
DeleteChild()
: 用于删除一个子元素。
GetText()
: 用于获取元素的文本内容。
SetText()
: 用于设置元素的文本内容。
Name()
: 用于获取元素的名称(标签名)。
Attribute()
: 用于获取元素的属性值。
FirstAttribute()
: 用于获取第一个属性。
NextAttribute()
: 用于获取下一个属性。
eg:对于<property name="ShowQuestClearCount" value="1"/>来说
Name 是property
Attribute 是name和value
Value 是ShowQuestClearCount和1
InsertEndChild()
: 用于将一个节点插入为父元素的最后一个子节点。
InsertFirstChild()
: 用于将一个节点插入为父元素的第一个子节点。