TinyXML2的一些用法

TinyXML2

      • 原始字符串字面量
    • TinyXML2
      • 1. XML文档操作
        • 1.1 LoadFile(const char* filename)
        • 1.2SaveFile(const char* filename)
        • 1.3RootElement()
        • 1.4Parse(const char* xml)
      • 2.元素操作
        • 2.1 FirstChildElement(const char* name = nullptr)
        • 2.2 NextSiblingElement(const char* name = nullptr)
        • 2.3 SetName(const char* name)
        • 2.4 DeleteChild(XMLElement* child)
      • 3. 属性操作
        • 3.1SetAttribute(const char* name, const char* value)
        • 3.2 Attribute(const char* name)
        • 3.3 DeleteAttribute(const char* name)
      • 4. 文本操作
        • 4.1 SetText(const char* text)
        • 4.2 GetText()
      • 5. 新建元素和节点
        • 5.1 NewElement(const char* name)
        • 5.2 InsertFirstChild(XMLNode* child)
        • 5.3 InsertEndChild(XMLNode* child)
      • 6. 错误处理
        • 6.1 ErrorID()
        • 6.2ErrorStr()
    • 附录:XML文件格式
      • 命名空间
      • 模式位置
      • 简单的XML文件
      • 复杂的XML文件

原始字符串字面量

  • 原始字符串字面量是 C++ 提供的一种字符串表示法,用来简化特殊字符的处理(例如换行符、反斜杠)和避免过多的转义字符。它的引入是为了让字符串更可读、更易于书写,尤其是涉及正则表达式、文件路径等场景。
  • 语法
原始字符串字面量以 R"delimiter(raw_characters)delimiter" 的形式表示:delimiter 是用户定义的分隔符,可以用任意字符,但不能包含空白字符或括号。
raw_characters 是原始字符串的内容,所有字符将被保留原样。
  • 特点
    • 支持多行字符串:原始字符串字面量可以直接包含换行符,而无需使用 \n。
    • 无需转义字符:在常规字符串中,特殊字符(如换行符 \n 或双引号 ")需要用反斜杠 \ 转义。
    • 灵活的分隔符:如果字符串中包含了 “)”,可以使用自定义分隔符避免冲突。
    std::string raw_str = R"delimiter(This is a raw string with ")".)delimiter";
    • 可嵌套引号:原始字符串字面量允许在字符串中直接包含双引号。
  • 使用方法同普通字符串一样。

TinyXML2

  1. TinyXML2 是一个轻量级的 XML 解析库,专为简单和快速设计,适合嵌入式系统、小型应用或需要解析/生成 XML 的程序。TinyXML2 的核心功能包括 XML 的读取、修改和写入。
  2. 跨平台:纯 C++ 编写,可在 Windows、Linux、macOS 等平台上使用。
  3. 无需外部依赖:仅需单个头文件和源文件(tinyxml2.h 和 tinyxml2.cpp)。

1. XML文档操作

1.1 LoadFile(const char* filename)

功能:将 XML 文档保存到文件。
参数:filename 是文件路径。
返回值:保存成功返回 XML_SUCCESS,否则返回错误码。

XMLDocument doc;//表示整个 XML 文件,负责加载、解析、保存。
if (doc.LoadFile("example.xml") != XML_SUCCESS) {std::cerr << "Failed to load XML file!" << std::endl;
}
1.2SaveFile(const char* filename)

功能:将 XML 文档保存到文件。
参数:filename 是文件路径。
返回值:保存成功返回 XML_SUCCESS,否则返回错误码。

if (doc.SaveFile("output.xml") != XML_SUCCESS) {std::cerr << "Failed to save XML file!" << std::endl;
}
1.3RootElement()

功能:获取 XML 文档的根元素。
返回值:指向根元素的指针,如果没有根元素返回 nullptr。

XMLElement* root = doc.RootElement();
if (!root) {std::cerr << "No root element found!" << std::endl;
} else {std::cout << "Root element: " << root->Name() << std::endl;
}
1.4Parse(const char* xml)

功能:直接解析 XML 字符串。
参数:xml 是一个 XML 格式的字符串。
返回值:解析成功返回 XML_SUCCESS,否则返回错误码。

const char* xml = "<Root><Child>Text</Child></Root>";
if (doc.Parse(xml) != XML_SUCCESS) {std::cerr << "Failed to parse XML string!" << std::endl;
}
示例// 1. 基本解析
XMLDocument doc;
// 解析简单的XML字符串
const char* xml = "<Root><Child>Hello</Child></Root>";
if (doc.Parse(xml) == XML_SUCCESS) {XMLElement* root = doc.FirstChildElement("Root");XMLElement* child = root->FirstChildElement("Child");const char* text = child->GetText();  // 获取 "Hello"
}// 2. 解析带属性的XML
const char* xmlWithAttr = R"(<Person id="1" name="John"><Age>30</Age><Address city="New York"><Street>Broadway</Street></Address></Person>
)";
if (doc.Parse(xmlWithAttr) == XML_SUCCESS) {XMLElement* person = doc.FirstChildElement("Person");const char* name = person->Attribute("name");  // 获取 "John"XMLElement* address = person->FirstChildElement("Address");const char* city = address->Attribute("city");  // 获取 "New York"
}// 3. 解析列表数据
const char* xmlList = R"(<Inventory><Item id="1" name="Apple" price="0.5"/><Item id="2" name="Banana" price="0.3"/><Item id="3" name="Orange" price="0.4"/></Inventory>
)";
class InventoryParser {
public:struct Item {int id;string name;double price;};static vector<Item> parseItems(const char* xml) {vector<Item> items;XMLDocument doc;if (doc.Parse(xml) == XML_SUCCESS) {XMLElement* inventory = doc.FirstChildElement("Inventory");for (XMLElement* elem = inventory->FirstChildElement("Item");elem != nullptr;elem = elem->NextSiblingElement("Item")) {Item item;item.id = elem->IntAttribute("id");item.name = elem->Attribute("name");item.price = elem->DoubleAttribute("price");items.push_back(item);}}return items;}
};// 4. 解析嵌套结构
const char* xmlNested = R"(<Company><Department name="Engineering"><Employee id="1"><Name>John Doe</Name><Position>Developer</Position><Skills><Skill>C++</Skill><Skill>Python</Skill></Skills></Employee></Department></Company>
)";
class CompanyParser {
public:static void parseEmployee(XMLElement* empElement) {string name = empElement->FirstChildElement("Name")->GetText();string position = empElement->FirstChildElement("Position")->GetText();vector<string> skills;XMLElement* skillsElem = empElement->FirstChildElement("Skills");for (XMLElement* skill = skillsElem->FirstChildElement("Skill");skill != nullptr;skill = skill->NextSiblingElement("Skill")) {skills.push_back(skill->GetText());}}
};// 5. 错误处理
class XMLParser {
public:static bool parseWithErrorHandling(const char* xml) {XMLDocument doc;XMLError err = doc.Parse(xml);switch (err) {case XML_SUCCESS:return true;case XML_ERROR_FILE_NOT_FOUND:cerr << "XML file not found!" << endl;break;case XML_ERROR_PARSING_ELEMENT:cerr << "Error parsing element!" << endl;break;case XML_ERROR_PARSING_ATTRIBUTE:cerr << "Error parsing attribute!" << endl;break;default:cerr << "Unknown XML error!" << endl;}return false;}
};// 6. 配置文件解析
const char* configXml = R"(<Config><Database><Host>localhost</Host><Port>3306</Port><Username>root</Username><Password>secret123</Password></Database><Server><Port>8080</Port><MaxConnections>100</MaxConnections></Server></Config>
)";
class ConfigParser {
public:struct DBConfig {string host;int port;string username;string password;};struct ServerConfig {int port;int maxConnections;};static pair<DBConfig, ServerConfig> parseConfig(const char* xml) {XMLDocument doc;DBConfig db;ServerConfig server;if (doc.Parse(xml) == XML_SUCCESS) {XMLElement* config = doc.FirstChildElement("Config");// 解析数据库配置XMLElement* dbElem = config->FirstChildElement("Database");db.host = dbElem->FirstChildElement("Host")->GetText();db.port = atoi(dbElem->FirstChildElement("Port")->GetText());db.username = dbElem->FirstChildElement("Username")->GetText();db.password = dbElem->FirstChildElement("Password")->GetText();// 解析服务器配置XMLElement* serverElem = config->FirstChildElement("Server");server.port = atoi(serverElem->FirstChildElement("Port")->GetText());server.maxConnections = atoi(serverElem->FirstChildElement("MaxConnections")->GetText());}return {db, server};}
};

2.元素操作

2.1 FirstChildElement(const char* name = nullptr)

功能:获取元素的第一个子元素。如果 name 参数不为空,则返回名称匹配的第一个子元素。
参数:name 是可选参数,表示子元素的名称。
返回值:指向第一个子元素的指针,如果没有找到返回 nullptr。

XMLElement* firstChild = root->FirstChildElement();
if (firstChild) {std::cout << "First child element: " << firstChild->Name() << std::endl;
}
2.2 NextSiblingElement(const char* name = nullptr)

功能:获取当前元素的下一个同级元素。如果 name 参数不为空,则返回名称匹配的下一个同级元素。
参数:name 是可选参数,表示同级元素的名称。
返回值:指向下一个同级元素的指针,如果没有找到返回 nullptr。

for (XMLElement* child = root->FirstChildElement(); child != nullptr; child = child->NextSiblingElement()) {std::cout << "Sibling element: " << child->Name() << std::endl;
}
2.3 SetName(const char* name)

功能:设置元素的名称。
参数:name 是新名称的字符串。

element->SetName("NewName");
2.4 DeleteChild(XMLElement* child)

功能:删除当前元素的指定子元素。
参数:child 是需要删除的子元素指针。

root->DeleteChild(child);

3. 属性操作

3.1SetAttribute(const char* name, const char* value)

功能:设置元素的字符串属性。
参数:name 是属性名,value 是属性值。

element->SetAttribute("key", "value");
3.2 Attribute(const char* name)

功能:获取元素指定名称的属性值。
参数:name 是属性名。
返回值:指向属性值的字符串指针,如果属性不存在返回 nullptr。

const char* attrValue = element->Attribute("key");
if (attrValue) {std::cout << "Attribute value: " << attrValue << std::endl;
}
3.3 DeleteAttribute(const char* name)

功能:删除元素指定名称的属性。
参数:name 是属性名。

element->DeleteAttribute("key");

4. 文本操作

4.1 SetText(const char* text)

功能:设置元素的文本内容。
参数:text 是字符串,表示要设置的文本内容。

element->SetText("This is text content");
4.2 GetText()

功能:获取元素的文本内容。
返回值:指向文本内容的字符串指针,如果没有文本内容返回 nullptr。

const char* text = element->GetText();
if (text) {std::cout << "Text content: " << text << std::endl;
}

5. 新建元素和节点

5.1 NewElement(const char* name)

功能:创建一个新的元素。
参数:name 是新元素的名称。
返回值:指向新创建的元素的指针。

XMLElement* newElement = doc.NewElement("NewElement");
5.2 InsertFirstChild(XMLNode* child)

功能:将一个子元素插入到当前元素的最前面。
参数:child 是要插入的子元素指针。

root->InsertFirstChild(newElement);
5.3 InsertEndChild(XMLNode* child)

功能:将一个子元素插入到当前元素的末尾。
参数:child 是要插入的子元素指针。

root->InsertEndChild(newElement);

6. 错误处理

6.1 ErrorID()

功能:返回文档的错误代码。

if (doc.ErrorID() != XML_SUCCESS) {std::cerr << "Error occurred: " << doc.ErrorID() << std::endl;
}
6.2ErrorStr()

功能:返回错误信息字符串。

if (doc.ErrorID() != XML_SUCCESS) {std::cerr << "Error details: " << doc.ErrorStr() << std::endl;
}

附录:XML文件格式

  1. XML的基本结构

    • 声明部分
      XML文件的开头是声明,表示XML的版本和编码格式
    <?xml version="1.0" encoding="UTF-8"?>
    • 根元素
      XML文件必须有且只有一个根元素,所有其他内容都嵌套在根元素中
    <root><!-- 子元素 -->
    </root>
    • 元素
      元素是XML的基本组成单位,通常由开始标签和结束标签组成
    <element>内容</element>
    
     - 可以嵌套子元素。- 可以携带属性
    
    <element attribute="value">内容</element>
     - 属性
    

    属性是描述元素的附加信息,格式为key=“value”

    <book id="1" author="Author Name">Book Title</book>
     - 注释
    

    注释用于添加说明性文字

    <!-- 这是一个注释 -->
    
     - 文本内容
    
    <name>张三</name>
  2. XML规则
    - 标签匹配
    标签匹配:每个开始标签必须有对应的结束标签

    <name>张三</name>

    单标签形式需要使用斜杠
    - 区分大小写
    XML区分大小写,例如和是不同的标签。
    - 属性值必须使用引号:可以是单引号或双引号

    <person gender="male"></person>
  3. 转义字符

特殊字符转义符示例代码输出效果
&&amp;<text>AT&amp;T</text><text>AT&T</text>
<&lt;<text>1 &lt; 2</text><text>1 < 2</text>
>&gt;<text>3 &gt; 2</text><text>3 > 2</text>
'&apos;<attribute value='John&apos;s book' /><attribute value='John's book' />
"&quot;<attribute value="He said &quot;Hello&quot;" /><attribute value="He said "Hello"" />

命名空间

  1. 由来
  • XML 中,标签名是自由定义的,不同的 XML 文档中可能会出现相同名称的标签。如果多个 XML 文件需要合并或扩展,很容易发生命名冲突。命名空间为标签和属性分配一个唯一的标识符,解决了冲突问题。
  • 命名空间实际上是一个唯一的 URI(Uniform Resource Identifier),通常是一个 URL(但不需要真实存在)。它标识某一组标签属于特定的上下文。
  1. 语法
  • 默认命名空间
<root xmlns="http://example.com/namespace"><child>Content</child>
</root>
<!--作用范围:没有前缀的所有标签(<root><child>)都属于这个命名空间。-->
  • 带前缀的命名空间
<root xmlns:ns="http://example.com/namespace"><ns:child>Content</ns:child>
</root>
<!--xmlns:ns="http://example.com/namespace" 声明了带前缀的命名空间-->
<!--标签 <ns:child> 使用了 ns 前缀,表示它属于命名空间 http://example.com/namespace-->
<!--作用范围:只有使用了 ns: 前缀的标签。-->
  • 解决的问题
<person xmlns:p="http://example.com/person"><p:name>John</p:name>
</person><product xmlns:prod="http://example.com/product"><prod:name>Smartphone</prod:name>
</product>

模式位置

简单的XML文件

<?xml version="1.0" encoding="UTF-8"?>
<!-- 这是一个简单的 XML 文件,描述书店中的书籍信息 -->
<bookstore><book id="1"><title>XML Basics</title><author>John Doe</author><price currency="USD">29.99</price></book><book id="2"><title>Learning XML</title><author>Jane Smith</author><price currency="EUR">39.99</price></book>
</bookstore>

复杂的XML文件

<?xml version="1.0" encoding="UTF-8"?>
<!-- 复杂 XML 文件,描述一个电子商务平台的订单信息 -->
<ecommerce xmlns="http://example.com/ecommerce" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://example.com/ecommerce ecommerce.xsd"><order id="1001" status="shipped"><customer><name>John Doe</name><email>john.doe@example.com</email><phone>+123456789</phone><address><street>123 Main St</street><city>Springfield</city><state>IL</state><zipcode>62704</zipcode><country>USA</country></address></customer><items><item id="p101"><name>Smartphone</name><quantity>1</quantity><price currency="USD">699.99</price></item><item id="p102"><name>Wireless Headphones</name><quantity>2</quantity><price currency="USD">59.99</price></item></items><payment><method>Credit Card</method><transaction_id>TX123456789</transaction_id><amount currency="USD">819.97</amount></payment><shipping><method>Express</method><tracking_number>EXP123456789</tracking_number><date>2024-11-25</date></shipping></order>
</ecommerce>

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GateWay使用手册

好的&#xff0c;下面是优化后的版本。为了提高可读性和规范性&#xff0c;我对内容进行了结构化、简化了部分代码&#xff0c;同时增加了注释说明&#xff0c;便于理解。 1. 引入依赖 在 pom.xml 中添加以下依赖&#xff1a; <dependencies><!-- Spring Cloud Gate…

SpringBoot+Flowable快速实现工流_动态选择审批人员

前言 OA系统中的工作流不仅是企业日常运营的重要组成部分&#xff0c;也是实现企业数字化转型、提高工作效率和执行力的重要工具。 在国内大部分的工作流系统使用Activiti框架实现。 其实flowable也可以轻松实现工作流业务。在线体验JeecgFlow flowable简介 Flowable是一个使用…

【ONE·基础算法 || 动态规划(三)】

总言 主要内容&#xff1a;编程题举例&#xff0c;熟悉理解动态规划类题型&#xff08;回文串问题、两个数组的 dp问题&#xff09;。                文章目录 总言7、回文串问题7.1、 回文子串&#xff08;medium&#xff09;7.1.1、题解 7.2、 最长回文子串&#…

Python 3 教程第33篇(MySQL - mysql-connector 驱动)

Python MySQL - mysql-connector 驱动 MySQL 是最流行的关系型数据库管理系统&#xff0c;如果你不熟悉 MySQL&#xff0c;可以阅读我们的 MySQL 教程。 本章节我们为大家介绍使用 mysql-connector 来连接使用 MySQL&#xff0c; mysql-connector 是 MySQL 官方提供的驱动器。…

LLM*:路径规划的大型语言模型增强增量启发式搜索

路径规划是机器人技术和自主导航中的一个基本科学问题&#xff0c;需要从起点到目的地推导出有效的路线&#xff0c;同时避开障碍物。A* 及其变体等传统算法能够确保路径有效性&#xff0c;但随着状态空间的增长&#xff0c;计算和内存效率会严重降低。相反&#xff0c;大型语言…

【Db First】.NET开源 ORM 框架 SqlSugar 系列

.NET开源 ORM 框架 SqlSugar 系列 【开篇】.NET开源 ORM 框架 SqlSugar 系列【入门必看】.NET开源 ORM 框架 SqlSugar 系列【实体配置】.NET开源 ORM 框架 SqlSugar 系列【Db First】.NET开源 ORM 框架 SqlSugar 系列【Code First】.NET开源 ORM 框架 SqlSugar 系列【数据事务…

企业品牌曝光的新策略:短视频矩阵系统

企业品牌曝光的新策略&#xff1a;短视频矩阵系统 在当今数字化时代&#xff0c;短视频已经渗透到我们的日常生活之中&#xff0c;成为连接品牌与消费者的关键渠道。然而&#xff0c;随着平台于7月20日全面下线了短视频矩阵的官方接口&#xff0c;许多依赖于此接口的小公司和内…

006 MATLAB编程基础

01 M文件 MATLAB输入命令有两种方法&#xff1a; 一是在MATLAB主窗口逐行输入命令&#xff0c;每个命令之间用分号或逗号分隔&#xff0c;每行可包含多个命令。 二是将命令组织成一个命令语句文集&#xff0c;使用扩展名“.m”&#xff0c;称为M文件。它由一系列的命令和语句…

Java基于SpringBoot+Vue的IT技术交流和分享平台(附源码+lw+部署)

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

【计算机网络】实验3:集线器和交换器的区别及交换器的自学习算法

实验 3&#xff1a;集线器和交换器的区别及交换器的自学习算法 一、 实验目的 加深对集线器和交换器的区别的理解。 了解交换器的自学习算法。 二、 实验环境 • Cisco Packet Tracer 模拟器 三、 实验内容 1、熟悉集线器和交换器的区别 (1) 第一步&#xff1a;构建网络…

UICollectionView在xcode16编译闪退问题

使用xcode15运行工程&#xff0c;控制台会出现如下提示&#xff1a; Expected dequeued view to be returned to the collection view in preparation for display. When the collection views data source is asked to provide a view for a given index path, ensure that a …

Proteus8.17下载安装教程

Proteus是一款嵌入式系统仿真开发软件&#xff0c;实现了从原理图设计、单片机编程、系统仿真到PCB设计&#xff0c;真正实现了从概念到产品的完整设计&#xff0c;其处理器模型支持8051、HC11、PIC10/12/16/18/24/30/DsPIC33、AVR、ARM、8086和MSP430等&#xff0c;能够帮助用…

Vue教程|搭建vue项目|Vue-CLI2.x 模板脚手架

一、项目构建环境准备 在构建Vue项目之前&#xff0c;需要搭建Node环境以及Vue-CLI脚手架&#xff0c;由于本篇文章为上一篇文章的补充&#xff0c;也是为了给大家分享更为完整的搭建vue项目方式&#xff0c;所以环境准备部分采用Vue教程&#xff5c;搭建vue项目&#xff5c;V…

一款支持80+语言,包括:拉丁文、中文、阿拉伯文、梵文等开源OCR库

大家好&#xff0c;今天给大家分享一个基于PyTorch的OCR库EasyOCR&#xff0c;它允许开发者通过简单的API调用来读取图片中的文本&#xff0c;无需复杂的模型训练过程。 项目介绍 EasyOCR 是一个基于Python的开源项目&#xff0c;它提供了一个简单易用的光学字符识别&#xff…

cocotb pytest

打印python中的print &#xff0c; 应该使用 pytest -s

【C++】STL——map和set

目录 1、序列式容器和关联式容器前 2、set 2.1 set类的介绍 2.2 set的构造和迭代器 2.3 set的增删查 set 的插入 set的查找 set的删除 2.4 multiset和set的差异 3、map 3 .1 pair类型 3.2 map的构造 3.3 map的增删查 map的构造遍历 map的插入 map的删除 map的查…

java基础概念46-数据结构1

一、引入 List集合的三种实现类使用了不同的数据结构&#xff01; 二、数据结构的定义 三、常见的数据结构 3-1、栈 特点&#xff1a;先进后出&#xff0c;后进先出。 java内存容器&#xff1a; 3-2、队列 特点&#xff1a;先进先出、后进后出。 栈VS队列-小结 3-3、数组 3-…

Docker:在 ubuntu 系统上生成和加载 Docker 镜像

本文将介绍在 ubuntu系统上进行 Docker 镜像的生成和加载方法和代码。 文章目录 一、下载和安装 docker二、加载 docker 文件三、保存你的镜像四、将镜像上传到云端并通过连接下载和加载 Docker 镜像五、Docker 容器和本地的文件交互5.1 从容器复制文件到本地宿主机5.1.1 单个文…

《数据挖掘:概念、模型、方法与算法(第三版)》

嘿&#xff0c;数据挖掘的小伙伴们&#xff01;今天我要给你们介绍一本超级实用的书——《数据挖掘&#xff1a;概念、模型、方法与算法》第三版。这本书是数据挖掘领域的经典之作&#xff0c;由该领域的知名专家编写&#xff0c;系统性地介绍了在高维数据空间中分析和提取大量…

做异端中的异端 -- Emacs裸奔之路4: 你不需要IDE

确切地说&#xff0c;你不需要在IDE里面编写或者阅读代码。 IDE用于Render资源文件比较合适&#xff0c;但处理文本&#xff0c;并不划算。 这的文本文件&#xff0c;包括源代码&#xff0c;配置文件&#xff0c;文档等非二进制文件。 先说说IDE带的便利: 函数或者变量的自动…