新的一周又来啦,这周我要分享的是使用C++库解析XML文件和JSON文件,在本篇博客中我主要讲解析XML文件的相关知识,在下篇博客讲述有关解析JSON文件的相关。在解析XML文件时我使用的解析库是tinyXML2,编译平台是VS2019。希望看完本篇博客能对你有所帮助。
XML文件简介
在学习解析XML文件之前我们应该先了解什么是XML文件。
XML文件是什么?
XML 指可扩展标记语言(eXtensible Markup Language),设计用来传输和存储数据。
- XML的设计宗旨是传输数据,而不是显示数据。
- XML 标签没有被预定义。您需要自行定义标签。
- XML 被设计为具有自我描述性。
XML的用途:
- XML 把数据从 HTML 分离
- XML 简化数据共享
- XML 简化数据传输
- XML 简化平台变更
- XML 使您的数据更有用
- XML 用于创建新的互联网语言
XML文件语法
XML文件的语法规则很简单主要包括以下几点:
- XML 文档必须有根元素
XML 必须包含根元素,它是所有其他元素的父元素,如以下实例中 root 就是根元素:
<root>
<child>
<subchild>.....</subchild>
</child>
</root>
- XML 声明
XML 声明文件的可选部分,如果存在需要放在文档的第一行,如下所示:
<?xml version="1.0" encoding="utf-8"?>
- 所有的 XML 元素都必须有一个关闭标签,但声明可以没有关闭标签
<p>This is a paragraph.</p>
- XML 标签对大小写敏感
XML 标签对大小写敏感。标签 与标签 是不同的。必须使用相同的大小写来编写打开标签和关闭标签:
Message>这是错误的</message>
<message>这是正确的</message>
- XML 必须正确嵌套
<b><i>This text is bold and italic</i></b>
- XML 属性值必须加引号
<note date=12/11/2007>
<to>Tove</to>
<from>Jani</from>
</note>
<note date="12/11/2007">
<to>Tove</to>
<from>Jani</from>
</note>
在上面两个XML文档中,第一个是错误的,第二个是正确的。
您如需了解更多关于XML文件的相关信息,可以到菜鸟教程学习相关知识。
在上面我介绍XML文件相关知识也都参考了该网站,有关知识介绍的都很全。
TinyXML2库及配置
在了解完XML文件的相关知识后,我们就可以开始进行XML文件的解析工作了。我们可以利用现成开源的库来帮助我们解析XML文件,目前比较好用的库就是TinyXML2,只有两个文件分别是.h文件和.cpp文件。TinyXML2相关的库可以再网上很容易下到,也可以到我的github下载相关的库文件,网址如下:TinyXML2文件库下载
这个库里面也有两个相关的例子。
把库下好之后,就可以进行配置了,TinyXML2配置相比于jsoncpp容易很多,就只有两步:
- 把库文件导入到项目工程中。如图所示:
2.在代码头文件中引入头文件和命名空间
#include "tinyxml2.h"
using namespace tinyxml2;
创建XML文件
配置好库之后就可以依赖库创建XML文件了,先贴代码:
void createCodeXml()
{
XMLDocument xml;
//插入声明
XMLDeclaration* declaration = xml.NewDeclaration();
xml.InsertFirstChild(declaration);
//插入根节点
XMLElement* rootNode = xml.NewElement("wang");
xml.InsertEndChild(rootNode);
//新建一个name节点
XMLElement* root_1_name = xml.NewElement("name");
//新建name节点的文本wangqinghe
//XMLText* text_1_name = xml.NewText("wangqinghe");
把文本与name节点链接起来
//root_1_name->InsertFirstChild(text_1_name);
//新建一个age节点
XMLElement* root_1_age = xml.NewElement("age");
XMLText* text_1_age = xml.NewText("18");
root_1_age->SetAttribute("age", "secret");
root_1_age->InsertFirstChild(text_1_age);
//创建name节点的子节点
XMLElement* root_2_gender = xml.NewElement("gender");
XMLText* text_2_gender = xml.NewText("man");
root_2_gender->InsertFirstChild(text_2_gender);
//将gender节点变为name节点的子节点
root_1_name->InsertEndChild(root_2_gender);
//链接name节点与根节点
rootNode->InsertEndChild(root_1_name);
rootNode->InsertEndChild(root_1_age);
xml.SaveFile("wang.xml");
}
首先构造一个XML文档:
XMLDocument xml;
插入声明:
//插入声明
XMLDeclaration* declaration = xml.NewDeclaration();
xml.InsertFirstChild(declaration);
插入声明后先插入一个根节点:“wang”
//插入根节点
XMLElement* rootNode = xml.NewElement("wang");
xml.InsertEndChild(rootNode);
新建一个name节点:
XMLElement* root_1_name = xml.NewElement("name");
创建name节点的子节点“gender”,文本内容为“man”,此时两者还没关系。
XMLElement* root_2_gender = xml.NewElement("gender");
XMLText* text_2_gender = xml.NewText("man");
root_2_gender->InsertFirstChild(text_2_gender);
把节点“gender”设置为节点“name”的子节点
root_1_name->InsertEndChild(root_2_gender);
新建一个age 节点,文本内容为18:
XMLElement* root_1_age = xml.NewElement("age");
XMLText* text_1_age = xml.NewText("18");
root_1_age->SetAttribute("age", "secret");
root_1_age->InsertFirstChild(text_1_age);
把name节点和age节点设置为根节点的子节点,到此所有的节点都连接完毕:
rootNode->InsertEndChild(root_1_name);
rootNode->InsertEndChild(root_1_age);
最后保存文件,文件名为wang.xml:
xml.SaveFile("wang.xml");
至此就已经创建好一个简单的xml文件了,文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<wang>
<name>
<gender>man</gender>
</name>
<age age="secret">18</age>
</wang>
xml文件创建完毕。
解析XML文件
创建完XML文件之后,我们就可以根据XML的文件格式来解析对应的XML文件。先放代码:
void decodeXml()
{
//声明
XMLDocument xml;
//导入xml文件
if (xml.LoadFile("wang.xml") != XML_SUCCESS)
{
return;
}
//判断头文件是否为空
XMLElement* rootNode = xml.RootElement();
if (rootNode == NULL)
{
return;
}
//读取第一层信息
XMLElement* root_1_name = rootNode->FirstChildElement("name");
//读取第二层信息
XMLElement* root_2_gender = root_1_name->FirstChildElement("gender");
//信息输出
string text_gender = root_2_gender->GetText();
cout << "gender: "<<text_gender << endl;
//读取第一层信息
XMLElement* root_1_age = rootNode->FirstChildElement("age");
const XMLAttribute* att_1_age = root_1_age->FirstAttribute();
cout << att_1_age->Name() << ":" << att_1_age->Value() << endl;
string text_age = root_1_age->GetText();
cout << "age: " << text_age << endl;
}
读取信息的代码比较简单,通过注释应该能轻易理解,读取的文件就是我们上面生成的XML文件。
总的代码如下:
#include <iostream>
#include"tinyxml2.h"
using namespace std;
using namespace tinyxml2;
void example2()
{
XMLDocument doc;
doc.LoadFile("test.xml");
XMLElement* scene = doc.RootElement();
XMLElement* surface = scene->FirstChildElement("node");
while (surface)
{
XMLElement* surfaceChild = surface->FirstChildElement();
const char* content;
const XMLAttribute* attributeOfSurface = surface->FirstAttribute();
cout << attributeOfSurface->Name() << ":" << attributeOfSurface->Value() << endl;
while (surfaceChild)
{
content = surfaceChild->GetText();
surfaceChild = surfaceChild->NextSiblingElement();
cout << content << endl;
}
surface = surface->NextSiblingElement();
}
}
int main()
{
example2();
return 0;
}
另一种解析XML文件的代码:
首先是要解析的文件:
<?xml version="1.0" encoding="UTF-8"?>
<scene name="Depth">
<node type="camera">
<eye>0 10 10</eye>
<front>0 0 -1</front>
<refUp>0 1 0</refUp>
<fov>90</fov>
</node>
<node type="Sphere">
<center>0 10 -10</center>
<radius>10</radius>
</node>
<node type="Plane">
<direction>0 10 -10</direction>
<distance>10</distance>
</node>
</scene>
对应代码:
#include <iostream>
#include"tinyxml2.h"
using namespace std;
using namespace tinyxml2;
void example2()
{
XMLDocument doc;
doc.LoadFile("test.xml");
XMLElement* scene = doc.RootElement();
XMLElement* surface = scene->FirstChildElement("node");
while (surface)
{
XMLElement* surfaceChild = surface->FirstChildElement();
const char* content;
const XMLAttribute* attributeOfSurface = surface->FirstAttribute();
cout << attributeOfSurface->Name() << ":" << attributeOfSurface->Value() << endl;
while (surfaceChild)
{
content = surfaceChild->GetText();
surfaceChild = surfaceChild->NextSiblingElement();
cout << content << endl;
}
surface = surface->NextSiblingElement();
}
}
int main()
{
example2();
return 0;
}