C++解析XML文件_c++ xml解析-程序员宅基地

技术标签: C++  c++  xml  开发语言  

新的一周又来啦,这周我要分享的是使用C++库解析XML文件和JSON文件,在本篇博客中我主要讲解析XML文件的相关知识,在下篇博客讲述有关解析JSON文件的相关。在解析XML文件时我使用的解析库是tinyXML2,编译平台是VS2019。希望看完本篇博客能对你有所帮助。

XML文件简介

在学习解析XML文件之前我们应该先了解什么是XML文件。

XML文件是什么?

XML 指可扩展标记语言(eXtensible Markup Language),设计用来传输和存储数据。

  1. XML的设计宗旨是传输数据,而不是显示数据。
  2. XML 标签没有被预定义。您需要自行定义标签。
  3. XML 被设计为具有自我描述性。

XML的用途:

  • XML 把数据从 HTML 分离
  • XML 简化数据共享
  • XML 简化数据传输
  • XML 简化平台变更
  • XML 使您的数据更有用
  • XML 用于创建新的互联网语言

XML文件语法

XML文件的语法规则很简单主要包括以下几点:

  1. XML 文档必须有根元素

XML 必须包含根元素,它是所有其他元素的父元素,如以下实例中 root 就是根元素:

<root>
  <child>
    <subchild>.....</subchild>
  </child>
</root>
  1. XML 声明

XML 声明文件的可选部分,如果存在需要放在文档的第一行,如下所示:

<?xml version="1.0" encoding="utf-8"?>
  1. 所有的 XML 元素都必须有一个关闭标签,但声明可以没有关闭标签
<p>This is a paragraph.</p>
  1. XML 标签对大小写敏感

XML 标签对大小写敏感。标签 与标签 是不同的。必须使用相同的大小写来编写打开标签和关闭标签:

Message>这是错误的</message>
<message>这是正确的</message>
  1. XML 必须正确嵌套
<b><i>This text is bold and italic</i></b>
  1. 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容易很多,就只有两步:

  1. 把库文件导入到项目工程中。如图所示:
    在这里插入图片描述
    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;
}

xml格式数据转为无空格和换行符字符串

 XMLPrinter printer;
 xml.Accept(&printer); // 将Print打印到Xmlprint类中 即保存在内存中
 const char *xmlString = printer.CStr();
 return xmlString;

代码下载:
相关的代码下载

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_44722098/article/details/126323838

智能推荐

学习笔记(03):高并发下的Nginx性能优化实战-Nginx优势特点总结-程序员宅基地

文章浏览阅读87次。 高并发下的Nginx性能优化实战、解读Nginx的核心知识、掌握nginx核心原理?通过本期课程将解答我们的疑惑。_随着 nginx 发展,高并发、轻量的优势,近几年

Linux环境 docker启动redis命令_linux docker 重启 redis-程序员宅基地

文章浏览阅读1.1k次。docker启动redis命令_linux docker 重启 redis

【总结】插头DP-bzoj1210/2310/2331/2595_dp插头模型-程序员宅基地

文章浏览阅读325次。插头DP小结_dp插头模型

关于测试工作效率低的一些思考和改进方法_测试人员不足与改进-程序员宅基地

文章浏览阅读3.5k次。关于测试工作效率低的一些思考和改进方法引子  汇总统计了一下项目组近期测试项目实际工作量与基线工作量的对比,发现一个严重问题。就是工作效率特别低下。下面简单列举一下几个项目预期工作量和实际工作量以及时间耗费严重的地方、项目简要背景。  1、B版本测试。版本预期工作量15人天,实际耗费工作量在30人天。更为严重的是测试人员并没有因为测试周期延长和工作量投入加大而测试的更轻松,反而是测试期..._测试人员不足与改进

级联样式表_级联样式表| 第三部分-程序员宅基地

文章浏览阅读173次。级联样式表 CSS-难以成熟 (CSS — Difficult to maturation)Unlike software, the CSS specifications are developed by successive versions, which would allow a browser to refer to a particular version. CSS was devel..._级联样式表是哪年产生的

sql server学习笔记——批处理语句、存储过程_sql的批处理-程序员宅基地

文章浏览阅读1.7k次。目录批处理语句1、批处理语句简介示例一:示例二:存储过程一、什么是存储过程1、存储过程的简介2、存储过程包含的内容3、存储过程的优点4、存储过程的分类系统存储过程:用户定义存储过程5、常用的系统储存过程(1)一般常用的存储过程(2)xp_cmdshell二、创建存储过程1、定义存储过程的语法2、不带参数的存储过程3、带参数..._sql的批处理

随便推点

dind(docker in docker)学习-程序员宅基地

文章浏览阅读1.1w次。docker in docker说白了,就是在docker容器内启动一个docker daemon,对外提供服务。优点在于:镜像和容器都在一个隔离的环境,保持操作者的干净环境。想到了再补充 :)一:低版本启动及访问启动1.12.6-dinddocker run --privileged -d --name mydocker docker:1.12.6-dind在其他容器访问d..._dind

com.sun.org.apache.xerces.internal.dom.DeferredTextImpl cannot be cast to org.w3c.dom.Element-程序员宅基地

文章浏览阅读1.4k次。代码 List<book> list = new ArrayList<book>(); Document doc = new DOCUntil().getDocument("src/ww/t/qp/books.xml"); Element root = doc.getDocumentElement(); NodeList books = root.getElementsByTagName("book"); for _com.sun.org.apache.xerces.internal.dom.deferredtextimpl cannot be cast to or

计算机网络 (ISP、计算机网络体系结构 拓扑图)-程序员宅基地

文章浏览阅读2.9k次。计算机网络定义: 一些互相连接的,自治的计算机或者智能硬件设备集合信息是如何交换的?1、电路交换(电话)线路被某个终端占用后不会被释放 除非主动释放2、分组交换分组交换是 把大数据拆分成小数据进行分组传输 提高传输效率计算机上的数据是突发的,所以不采用电路交换,而采用分组交换3、ISP(internet service provider)网络服务提供商终端通过交换机连接一级ISP(国际性区域)之间互相连接 某一条线路断后可以通过其他设备进行通信二级ISP(国家/区域性规模)与一级相互连接三级ISP(本地区域

集通字库芯片GT20L16S1Y 读取字体数据-程序员宅基地

文章浏览阅读3.5k次,点赞12次,收藏46次。/** * @brief * @note * @param None * @retval None * @author PWH * @date 2021/4 */int32_t GT20L16S1Y_Get_Addr_Ascii_7x8(char *asciiCode){ if (*asciiCode >= ' ' && *asciiCode <= '~') { return 0x66C0 + (*asciiCode - ._gt20l16s1y

关于ETH的NONCE_ethers获取交易nonce-程序员宅基地

文章浏览阅读1.3k次。最近我的ETH交易里面出现了一种情况,交易虽然返回了hash,但是却迟迟未被确认,连在区块浏览器上也找不到对应的pending交易, 但是通过节点api调用hash获取记忆记录却有数据返回。这种情况问了人也查了资料,最后得出的结果是,交易可能在矿池,但是却没有被矿工打包。于是想到了imtoken钱包的加速交易内容。说到加速交易,不得不说的就是ETH交易内重要的一个内容, nonce。nonc..._ethers获取交易nonce

Flutter Widget显示隐藏_flutter判断控制是否被遮住-程序员宅基地

文章浏览阅读7.6k次。在Android中我们可以用visibility来控制控件的显示和隐藏,那在Flutter中我们怎么控制呢?其实,在Flutter中控制Widget显示和隐藏有3中方法:不过3种方法的核心思想都是根据变量的值去判断的,所以先定义一个变量:bool visible = true;变量的值可以在事件中去控制,比如: onPressed: () { setS..._flutter判断控制是否被遮住

推荐文章

热门文章

相关标签