C++解析xml示例

news2025/1/12 19:39:14

C++解析xml示例

  • 1. Xml文档介绍
    • 1.1 特点及作用
    • 1.2 Xml优点
      • 1.2.1 良好的可拓展性
      • 1.2.2 内容与形式分离
    • 1.3 Xml组成
      • 1.3.1 Xml声明
      • 1.3.2 根元素
      • 1.3.3 元素
      • 1.3.4 属性
      • 1.3.5 实体
      • 1.3.6 注释
  • 2 C++解析Xml
    • 2.1 tinyXml2类库
    • 2.2 关键接口
      • 2.2.1 LoadFile
      • 2.2.2 RootElement
      • 2.2.3 FirstChildElement
      • 2.2.4 NextSiblingElement
      • 2.2.5 Value
      • 2.2.6 Attribute
      • 2.2.7 ToDeclaration
  • 3 搜索Xml中数据案例

1. Xml文档介绍

Xml(Extensible Markup Language)即可扩展标记语言,Xml是互联网数据传输的重要工具,它可以跨越互联网任何的平台,不受编程语言和操作系统的限制,可以说它是一个拥有互联网最高级别通行证的数据携带者。

Xml用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。Xml是标准通用标记语言(SGML)的子集,非常适合Web传输。Xml提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据。

在很多工具或服务中需要解析Xml,此文档供相关开发人员使用C++解析Xml做参考。

1.1 特点及作用

Xml特点:

  1. xml与操作系统、编程语言的开发平台都无关;
  2. 实现不同系统之间的数据交互;
    Xml作用:
  3. 配置应用程序和网站,在配置文件里几乎所有的配置文件都是以Xml的格式来编写的;
  4. 数据交互,即服务器以XML的形式传输数据;
  5. 储存数据;

1.2 Xml优点

1.2.1 良好的可拓展性

在XML产生之前,要想定义一个置标语言并推广利用它非常困难。一方面,如果制定了一个新的语言而期望它能生效,需要把这个标准提交给相关的组织(如W3C),等待它接受并正式公布这个标准,经过几轮的评定和修改,到这个置标语言终于成为一个正式推荐标准时,可能已经过了几年的时间。另一方面,为了让这套标记得到广泛应用,制订者必须为它配备浏览工具。这样,就不得不去游说各个浏览器厂商接受并支持新制定的标记,或者索性自己开发一个新的浏览器去与现有的浏览器竞争,无论哪个办法,都需要耗费大量的时间和工作。现在借助XML的帮助,制定新的置标语言要简单易行得多了,这也正是XML的优势所在。

各个不同的行业可能会有一些独特的要求,比如说,化学家需要化学公式中的一些特殊符号,建筑家需要设计图纸中的某些特殊的标记,音乐家需要音符,这些都需要单独的标记。但是,其他网页设计者一般不会用这些记号,也不需要这些标记。XML的优点就在于它允许各个组织、个人建立适合他们自己需要的标记库,并且这个标记库可以迅速地投入使用。

1.2.2 内容与形式分离

XML不仅允许自定义一套标记,而且这些标记不必仅限于对显示格式的描述。在XML中,显示样式从数据文档中分离出来,放在样式单文件中。这样,如果要改动信息的表现方式,无须改动信息本身,只要改动样式单文件就够了。如果这时候把列表的数据改用表格显示,无须再去修改大量数据信息文档,因为它们和同一个样式文件相关联,只要改动这个样式单文件就可以了。

在XML中数据搜索可以简单高效地进行。 若在HTML文件中搜索某个字符串,脚本会逐字寻找对应的字符串,即使找到了,若存在多个相同目标字符串,也不能确定是否为自己想要找到的那个。在XML中搜索不必要再去遍历整个文档,只需要找一下相关标记下的内容。此外,信息之间的某些复杂关系,比如树状结构、继承关系等,在XML中也都得到了绝好的体现,这样就大大方便了XML的应用处理程序的开发。

1.3 Xml组成

一个正规的Xml文档的结构需要有声明,文档元素描述信息(有且仅有一个根元素),元素属性。也可能包含实体,注释等信息。
在这里插入图片描述

1.3.1 Xml声明

在编写XML文档时,需要先使用文档声明来声明XML文档。且必须出现在文档的第一行。最简单的声明语法:

<?xml version="xxx"?>

Version后引号内的字符串表示文档的版本。

当我们写好的一个xml文件写入内存的时候会转换为二进制保存,这个时候会查码表,记事本保存的时候是gbk,而保存的时候默认查码表时用的是utf-8,这个时候我们就可以用encoding属性:默认是UTF-8

<?xml version="xxx” encoding="GBK"?>

这样就可以解决乱码等问题。

Xml声明还可能包含standlone属性:该xml文件是否独立存在。

1.3.2 根元素

根元素是Xml文档里面唯一的,它的开始是放在最前面,结束是放在最后面。
在这里插入图片描述

1.3.3 元素

根元素下的所有元素格式与根元素相同,其格式为:
在这里插入图片描述
Note

  1. 所有元素都必须有开始标签和结束标签;
  2. 开始标签和结束标签的名称必须相同(区分大小写);
  3. 元素title名称可以包含字母,数字或者其他字符,但是不能以数字或者符号开头,名称中不能包含空格;
  4. 名称字符之间不能使用冒号(有特殊用途);

1.3.4 属性

对于有属性的元素,语法结构为:

<元素名 属性名=“属性值”></元素名>

Note

  1. 属性值用双引号包括,一个元素可以有多个属性;
  2. 属性值中不能直接包含符号;

1.3.5 实体

在xml中,一些字符拥有特殊的意义。如果把字符“<”放在xml元素中,会发生错误,这是因为解析器会把它当作新元素的开始,这样会产生xml错误。

为了避免这个错误,在元素中需要引用这些字符时,用实体引用来代替字符。Xml中5个预定义实体:

实体符号
&It;<
>>
&&
"*
'.

1.3.6 注释

注释语法:
<!—注释内容–>
Note:

  1. 注释内容中不要出现“–”;
  2. 注释不能嵌套;
  3. XML声明之前不能有注释,不允许第一行写注释;

2 C++解析Xml

2.1 tinyXml2类库

在C++中读写Xml会用到一个C++库tinyXml2类库。这个库中包含了我们读取Xml所需的接口。

TinyXML2是一个开源、简单、小巧、高效的C++ XML解析器,可以轻松集成到其它程序中。目前存在两个著名的开源XML文件解析库:tinyXml1,tinyXml2。相对tinyXml1而言,tinyXml2更为简洁,它只有一个tinyXml2.h文件和一个tinyXml2.cpp文件组成,而tinyXml1包含了6个文件。

TinyXml2具有以下几个优点:

  1. 对大部分的C/C++项目具有普适性,并且拥有丰富的测试案例;
  2. 使用较少的内存(约 TinyXML1 的 40%),速度变得更快;
  3. 没有C++的STL要求;
  4. 更接近现代 C++ 的特性,如使用了适当的命名空间;
  5. 适当有效的处理了的空白字符(空格,Tab 和回车);

使用方法:将 tinyxml2.cpp 和 tinyxml2.h 拷贝至项目目录,使用时包含头文件和引入名字空间。

2.2 关键接口

2.2.1 LoadFile

作用:用于加载Xml文件

在这里插入图片描述

传参:LoadFile(FilePath)

一般使用格式:

if(Xml.LoadFile(FilePath)!=XML_SUCCESS)// 通过Xml文件路径读取文件,若读取失败则返回
	return;

2.2.2 RootElement

作用:用于读取Xml的根节点

在这里插入图片描述

传参:RootElement()

一般使用格式:

tinyxml2::XMLElement* rootElement = NULL;
rootElement=Xml.RootElement();//rootElement指向当前Xml的根节点
if(rootElement==NULL)//若读取失败则返回
return;

2.2.3 FirstChildElement

作用:用于读取xml节点的下一层节点
在这里插入图片描述
传参:(1)FirstChildElement()//读取下一层节点的第一个节点
(2)FirstChildElement(“XXX”)//读取下一层节点第一个元素名为“XXX”的节点

一般使用格式:

const XMLNode* Element1 = NULL;
Element1 = rootElement-> FirstChildElement(“XXX”);//Element1指向rootElement的下一层第一个元素名为”XXX”的节点
if(Element1 ==NULL)//若读取失败则返回
return;

2.2.4 NextSiblingElement

作用:用于读取Xml节点同层节点的下一个节点

在这里插入图片描述

传参:NextSiblingElement()

一般使用格式:

const XMLNode* Element2 = NULL;
Element2 = Element1 -> NextSiblingElement ();//Element2指向Element1的同层节点的下一个节点
if(Element2 ==NULL)//若读取失败则返回
return;

2.2.5 Value

作用:用于读取Xml节点的元素名

在这里插入图片描述

传参:Value()

一般使用格式:

String str1= Element2->Value();//将Element2的元素名赋值给str1

2.2.6 Attribute

作用:用于读取Xml节点的属性值

在这里插入图片描述
传参:Attribute()

一般使用格式:

String str2 = Element2->ToElement()->Attribute(“XXX”);//将Element2的属性名为”XXX”的属性值赋值给str2

2.2.7 ToDeclaration

作用:用于读取Xml文件的声明

在这里插入图片描述

传参:ToDeclaration()

一般使用格式:

tinyxml2::XMLDocument xmlParse;
if (xmlParse.LoadFile(str_xmlPath.c_str()) != tinyxml2::XML_SUCCESS)
	return -1;
XMLNode *decl= xmlParse.FirstChild();
if(NULL!= decl)
	{
	XMLDeclaration* declaration =decl->ToDeclaration();
string strDecl = declaration->Value();//最终将声明字符串赋值给strDecl
}

3 搜索Xml中数据案例

通常在Xml中搜索数据会有很多限制条件,需要通过层层搜索找到想要的数据。
在这里插入图片描述
如图中,若希望通过限制条件WwanDeviceConfigID-ID,FCC_MAP_INDEX_TYPE- Value,Standard- Vaule,Item- PSensors/ DeviceMode/ AntMode/ AntMode1找到对应的Item –SarIndex,代码案例如下,是一个对应的从Xml中搜索数据的接口(代码部分,仅供参考):

int CStateWork::GetSarIndexFromXml(string str_xmlPath, string WwanDeviceConfigID, string regmcc, string PSensors, string DeviceMode, string AntMode, string AntMode1)
	string SarIndex;
do
	{
1.初始化
		tinyxml2::XMLDocument xmlParse;
		tinyxml2::XMLElement* rootElement = NULL;
		const XMLNode* WwanDeviceConfigIDElement = NULL;
		const XMLNode* WwanDeviceConfigIDList = NULL;
		const XMLNode* FCC_MAP_INDEX_TYPE_Element = NULL;
		const XMLNode* MapTypeElement = NULL;
		const XMLNode* StandardElement = NULL;
		const XMLNode* ItemElement = NULL;
		string FCC_MAP_INDEX_TYPE;
int i_ret = -1;
2.加载Xml文件,并获取根节点
		if (xmlParse.LoadFile(str_xmlPath.c_str()) != tinyxml2::XML_SUCCESS)
		{
			return i_ret;
		}
		rootElement = xmlParse.RootElement();
		if (NULL == rootElement)
		{
			return i_ret;
		}
3.通过传参WwanDeviceConfigID,找到对应的WwanDeviceConfigID节点
		WwanDeviceConfigIDList = rootElement->FirstChildElement("WwanDeviceConfigIDList");
		if (NULL == WwanDeviceConfigIDList)
		{
			return i_ret;
		}
		WwanDeviceConfigIDElement = WwanDeviceConfigIDList->FirstChildElement("WwanDeviceConfigID");
		for (WwanDeviceConfigIDElement; WwanDeviceConfigIDElement; WwanDeviceConfigIDElement = WwanDeviceConfigIDElement->NextSiblingElement())
		{
			if (WwanDeviceConfigIDElement->ToElement()->Attribute("ID") == WwanDeviceConfigID)
				break;
		}

4.在WwanDeviceConfigID节点下,找到FCC_MAP_INDEX_TYPE节点的属性值
		FCC_MAP_INDEX_TYPE_Element = WwanDeviceConfigIDElement->FirstChildElement("FCC_MAP_INDEX_TYPE");
		if (NULL == FCC_MAP_INDEX_TYPE_Element)
		{
			return i_ret;
		}
		FCC_MAP_INDEX_TYPE = FCC_MAP_INDEX_TYPE_Element->ToElement()->Attribute("Value");

5.在WwanDeviceConfigID节点下,找到与FCC_MAP_INDEX_TYPE节点的属性值对应的MapType

		MapTypeElement = WwanDeviceConfigIDElement->FirstChildElement(FCC_MAP_INDEX_TYPE.c_str());
		if (NULL == MapTypeElement)
		{
			return i_ret;
		}

6.在MapType节点下,找到属性值与传参regmcc对应的Standard节点
		StandardElement = MapTypeElement->FirstChildElement("Standard");
		if (NULL == StandardElement)
		{
			return i_ret;
		}
		for (StandardElement; StandardElement; StandardElement = StandardElement->NextSiblingElement())
		{
			if (StandardElement->ToElement()->Attribute("Vaule") == regmcc)
				break;
		}

7.在Standard节点下,找到属性值与传参PSensors,DeviceMode,AntMode,AntMode1一一对应的Item节点(不同的MapType属性个数不同,需要先判断在哪个MapType下搜索)
		ItemElement = StandardElement->FirstChildElement("Item");
		if (NULL == ItemElement)
		{
			return i_ret;
		}
		if (FCC_MAP_INDEX_TYPE.find("MapType_1") != std::string::npos)
		{
			ItemElement = StandardElement->FirstChildElement();
			if (NULL == ItemElement)
			{
				return i_ret;
			}
		}
		else if (FCC_MAP_INDEX_TYPE.find("MapType_2") != std::string::npos)
		{
			if (PSensors == "")

			{
				return i_ret;
			}
			ItemElement = StandardElement->FirstChildElement();
			if (NULL == ItemElement)
			{
				return i_ret;
			}
			while (ItemElement->ToElement()->Attribute("PSensors") != PSensors)
			{
				ItemElement = ItemElement->NextSiblingElement();
				if (NULL == ItemElement)
				{
					return i_ret;
				}
			}
		}
		else if (FCC_MAP_INDEX_TYPE.find("MapType_3") != std::string::npos)
		{
			if (DeviceMode == "")
			{
				return i_ret;
			}
			ItemElement = StandardElement->FirstChildElement();
			if (NULL == ItemElement)
			{
				return i_ret;
			}
			while (ItemElement->ToElement()->Attribute("DeviceMode") != DeviceMode)
			{
				ItemElement = ItemElement->NextSiblingElement();
				if (NULL == ItemElement)
				{
					return i_ret;
				}
			}
		}
		else if (FCC_MAP_INDEX_TYPE.find("MapType_4") != std::string::npos)
		{
			if (PSensors == "")
			{
				return i_ret;
			}
			if (DeviceMode == "")
			{
				return i_ret;
			}
			ItemElement = StandardElement->FirstChildElement();
			if (NULL == ItemElement)
			{
				return i_ret;
			}
			while (ItemElement->ToElement()->Attribute("PSensors") != PSensors
				|| ItemElement->ToElement()->Attribute("DeviceMode") != DeviceMode)
			{
				ItemElement = ItemElement->NextSiblingElement();
				if (NULL == ItemElement)
				{
					return i_ret;
				}
			}
		}
		else if (FCC_MAP_INDEX_TYPE.find("MapType_5") != std::string::npos)
		{
			if (PSensors == "")
			{
				return i_ret;
			}
			if (AntMode == "")
			{	
				return i_ret;
			}
			if (AntMode1 == "")
			{
				return i_ret;
			}
			ItemElement = StandardElement->FirstChildElement();
			if (NULL == ItemElement)
			{
				return i_ret;
			}
			while (ItemElement->ToElement()->Attribute("PSensors") != PSensors
				|| ItemElement->ToElement()->Attribute("AntMode") != AntMode
				|| ItemElement->ToElement()->Attribute("AntMode1") != AntMode1)
			{
				ItemElement = ItemElement->NextSiblingElement();
				if (NULL == ItemElement)
				{
					return i_ret;
				}
			}
		}
		else if (FCC_MAP_INDEX_TYPE.find("MapType_6") != std::string::npos)
		{
			if (PSensors == "")
			{
				return i_ret;
			}
			if (AntMode == "")
			{
				return i_ret;
			}
			if (AntMode1 == "")
			{
				return i_ret;
			}
			if (DeviceMode == "")
			{
				return i_ret;
			}
			ItemElement = StandardElement->FirstChildElement();
			if (NULL == ItemElement)
			{
				return i_ret;
			}
			while (ItemElement->ToElement()->Attribute("PSensors") != PSensors
				|| ItemElement->ToElement()->Attribute("AntMode") != AntMode
				|| ItemElement->ToElement()->Attribute("AntMode1") != AntMode1
				|| ItemElement->ToElement()->Attribute("DeviceMode") != DeviceMode)
			{
				ItemElement = ItemElement->NextSiblingElement();
				if (NULL == ItemElement)
				{
					return i_ret;
				}
			}
		}

8.在Item节点下,读出SarIndex属性值,并作为最终接口的输出
		SarIndex = ItemElement->ToElement()->Attribute("SarIndex");
	} while (FALSE);
	return atoi(SarIndex.c_str());
}

Note:

  1. 在LoadFile Xml文件时,应该判断是否成功打开,若失败则返回;
  2. 在获取任何新的节点以及节点指向的位置变动后,应该判断当前节点是否为空,若为空则应该返回或做其他异常处理;
  3. 当前节点往下向子节点搜寻,一般直接用FirstChild函数直接实现,当前节点往下向同级节点搜寻,一般用NextSiblingElement函数遍历实现;
  4. 在同一个元素中可能会有多组属性和属性值,在这种情况下搜索相应的数据一般需要用循环,对于每一次循环都是获取一次新的节点,因此在循环前和每一次循环后都应该判断当前节点是否为空,以免出现crash

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1274599.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

重要通知丨JumpServer开源堡垒机V2社区版即将停止维护的通知

尊敬的JumpServer开源堡垒机用户&#xff1a;您好&#xff01; 如《关于JumpServer开源堡垒机V2版本产品生命周期的相关说明》所示&#xff0c;JumpServer开源堡垒机V2版本&#xff08;社区版&#xff09;将于2023年12月31日停止维护支持。 在过去两年多的时间里&#xff0c;…

第十一章 Shell编程

第十一章 Shell编程 ​ Shell程序是通过文本编辑程序把一系列Linux命令放在一个文件中执行的实用程序。执行Shell程序时&#xff0c;文件中的Linux命令会被一条接一条地边解释边执行。因此&#xff0c;当用户需要通过多个Linux命令地执行才能完成最后地操作时&#xff0c;可以…

【Docker】Swarm的ingress网络

Docker Swarm Ingress网络是Docker集群中的一种网络模式&#xff0c;它允许在Swarm集群中运行的服务通过一个公共的入口点进行访问。Ingress网络将外部流量路由到Swarm集群中的适当服务&#xff0c;并提供负载均衡和服务发现功能。 在Docker Swarm中&#xff0c;Ingress网络使…

Spring简单的存储和读取

前言 前面讲了spring的创建&#xff0c;现在说说关于Bean和五大类注解 一、Bean是什么&#xff1f; 在 Java 语⾔中对象也叫做 Bean&#xff0c;所以后⾯咱们再遇到对象就以 Bean 著称。这篇文章还是以spring创建为主。 二、存储对象 2.1 俩种存储方式 需要在 spring-conf…

借助ETL快速查询金蝶云星空表单信息

随着数字化转型的加速&#xff0c;企业信息化程度越来越高&#xff0c;大量的数据产生并存储在云端&#xff0c;需要进行有效的数据管理和查询。金蝶云星空是金蝶云旗下的一款云ERP产品&#xff0c;为企业提供了完整的业务流程和数据管理功能&#xff0c;因此需要进行有效的数据…

使用 CSS Grid 的响应式网页设计:消除媒体查询过载

文章目录 前言介绍 CSS Grid让我们开始吧实现高级响应性1、Repeat() 2、Auto-fit3、Minmax()结论 前言 你是否厌倦了在实现响应式网站时需要管理多个媒体查询&#xff1f;说再见复杂的代码&#xff0c;拥抱更简单的解决方案吧&#xff1a;CSS Grid。 在这篇文章中&#xff0c;…

血的教训---入侵redis并免密登录redis所在服务器漏洞复现

血的教训—入侵redis并免密登录redis所在服务器漏洞复现 今天就跟着我一起来入侵redis并免密登录redis所在服务器吧&#xff0c;废话不多说&#xff0c;我们直接开始吧。 这是一个体系的学习步骤&#xff0c;当然如果基础扎实的话可以继续往下面看 以下都是关联的文章&#xff…

MobaXterm连接相关

其实最终解决的方法&#xff0c;还是&#xff0c;因为要远程连接的是个局域网ip&#xff0c;我所在的ip和要连接的这个不在同一个局域网内&#xff0c;需要实验室搭的VPN才行。 甚至&#xff0c;我连防火墙都没关&#xff0c;也可以连接 至于修改密码&#xff0c;passwd&#…

应用于智慧金融的AI边缘计算盒子+AI算法软硬一体化方案

传统金融营业厅存在运营管理模式落后、资源投放不平衡、从业人员培训效果不达预期、客户体验割裂等普遍现象&#xff1b; 部署英码数字金融解决方案&#xff0c;将助力企业从传统金融模式快速向数字金融模式转变&#xff0c;可针对每一个客户定制个性化“一对一”服务&#xff…

算法与数据结构有区别吗?

算法和数据结构并不是同一件事。严格来说&#xff0c;它们并不是等效的。但是&#xff0c;我们通常在使用的时候会互换这两个术语。为了简便&#xff0c;后文我们会用数据结构这个术语来指代“数据结构及其所有相关的方法”。 有很多方法可以用来说明这两个术语之间的区别&…

Linux信号超详细剖析

预备知识&#xff1a; 一、信号产生(OS发给进程) 1、键盘组合键 Linux中&#xff0c;一次登录对应一个终端&#xff0c;bash/shell。且只允许一个进程是前台进程&#xff0c;默认就是bash/shell&#xff0c;其它都是后台进程。获取键盘输入的是前台进程。 Ctrlc: 向前台进程…

Nginx配置文件全解析【深度剖析细节】

文章目录 &#x1f4a5; 简介&#x1f4ab; 基本结构&#x1f349; 事件处理器&#x1f96d; 配置分析&#x1f34f; 配置示例 &#x1f349; HTTP服务器&#x1f96d; 配置分析&#x1f34f; 配置示例 &#x1f349; 虚拟主机 &#x1f34a; 优化&#x1f354; 总结 &#x1f…

02-使用Git命令操作远程仓库,如克隆或添加远程仓库,拉取或推送内容

操作远程仓库 创建远程仓库 第一步: 访问GitHub官网,登录自己的账号创建一个远程仓库 第二步: 设置远程仓库的信息(一般远程库的名字和本地库的名字一样),仓库创建完成后可以看到仓库地址(每个仓库都会对应一个网络地址) 第三步: 查看本地仓库对应的Https/SSH连接 远程仓库命…

【负载均衡 SLB介绍及其算法详解】(一万两千字)

目录 一、负载均衡 SLB 定义 二、负载均衡SLB的作用 三、负载均衡器&#xff08;Load Balancer&#xff09; 【1】工作原理 【2】主要功能 【3】关键概念 四、工作负载&#xff08;Workload&#xff09; 五、负载均衡算法 【1】轮询&#xff08;Round Robin&#xff0…

Oracle(2-8)Configuring the Database Archiving Mode

文章目录 一、基础知识1、Redo Log History2、NOARCHIVELOG Mode 非归档模式3、ARCHIVELOG Mode 归档模式4、Changing the Archiving Mode 更改归档模式![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/d6a09f9a6de24de7bbcdad90b8d6b9ca.png)5、Auto and Manual Ar…

图扑参展高交会-全球清洁能源创新博览会

“相聚鹏城深圳&#xff0c;共享能源盛宴” 第二十五届中国国际高新技术成果交易会(简称“高交会”)于 11 月 15-18 日在深圳盛大开幕。高交会由商务部、科学技术部、工业和信息化部、国家发展改革委、农业农村部、国家知识产权局、中国科学院、中国工程院和深圳市人民政府共同…

从零开始Inline Hook

中断表进入0环 通过中断门进入0环&#xff0c;首先了解一下中断门的构成 构造一个中断号 Base:函数地址 DPL:3 //因为三环使用调用门的条件就是CPL(即cs段选择子的RPL)<DPL P:1 //P为1时&#xff0c;中断表才有效 Segment Selector: 0x0008 //中断成功后切换自己的CPL 在…

生产制造中4种导致产品成本、库存核算差错的问题!(化工/化妆品/生物制剂/混凝土等行业ODOO)

在化工/化妆品/生物制剂/混凝土等行业&#xff0c;因为其生产物料及产成品大都以液体&#xff08;或散颗粒&#xff09;形态为主&#xff0c;多以重量为计数方式&#xff1b;且液体&#xff08;或散颗粒&#xff09;相较于固体的较大区别就是产品计数上变数较大&#xff0c;固体…

“掌握速卖通平台接口:电商开发的技术巅峰“

一、概述 速卖通平台接口是全球速卖通提供的一套API接口&#xff0c;旨在为开发者提供与速卖通平台进行数据交互的能力。通过使用速卖通平台接口&#xff0c;开发者可以快速构建自己的电商应用程序&#xff0c;并实现与速卖通平台的数据共享和交易流程。本文将详细介绍速卖通平…

List集合,遍历,数据结构

一.List常见的方法&#xff1a; 二. List集合的遍历方式 除了 迭代器遍历 增强for遍历 Lambda表达式遍历&#xff0c;还有自己独有的普通for遍历&#xff0c;列表迭代器遍历 1.迭代器遍历 2.增强for遍历 3.Lambda表达式遍历 4.普通for遍历 5.列表迭代器遍历 列表迭代器相对于…