TinyXML2的一些用法

[复制链接]
发表于 2025-12-16 21:35:45 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
原始字符串字面量



  • 原始字符串字面量是 C++ 提供的一种字符串表现法,用来简化特别字符的处置惩罚(比方换行符、反斜杠)和克制过多的转义字符。它的引入是为了让字符串更可读、更易于誊写,尤其是涉及正则表达式、文件路径等场景。
  • 语法
  1. 原始字符串字面量以 R"delimiter(raw_characters)delimiter" 的形式表示:
  2. delimiter 是用户定义的分隔符,可以用任意字符,但不能包含空白字符或括号。
  3. raw_characters 是原始字符串的内容,所有字符将被保留原样。
复制代码


  • 特点

    • 支持多行字符串:原始字符串字面量可以直接包罗换行符,而无需利用 \n。
    • 无需转义字符:在通例字符串中,特别字符(如换行符 \n 或双引号 ")必要用反斜杠 \ 转义。
    • 机动的分隔符:如果字符串中包罗了 “)”,可以利用自界说分隔符克制辩说。
    1. std::string raw_str = R"delimiter(This is a raw string with ")".)delimiter";
    复制代码
      

    • 可嵌套引号:原始字符串字面量答应在字符串中直接包罗双引号。

  • 利用方法同平常字符串一样。
TinyXML2


  • TinyXML2 是一个轻量级的 XML 分析库,专为简朴和快速计划,恰当嵌入式体系、小型应用或必要分析/天生 XML 的步调。TinyXML2 的焦点功能包罗 XML 的读取、修改和写入。
  • 跨平台:纯 C++ 编写,可在 Windows、Linux、macOS 等平台上利用。
  • 无需外部依赖:仅需单个头文件和源文件(tinyxml2.h 和 tinyxml2.cpp)。
1. XML文档利用

1.1 LoadFile(const char* filename)

功能:将 XML 文档生存到文件。
参数:filename 是文件路径。
返回值:生存乐成返回 XML_SUCCESS,否则返回错误码。
  1. XMLDocument doc;//表示整个 XML 文件,负责加载、解析、保存。
  2. if (doc.LoadFile("example.xml") != XML_SUCCESS) {
  3.     std::cerr << "Failed to load XML file!" << std::endl;
  4. }
复制代码
1.2SaveFile(const char* filename)

功能:将 XML 文档生存到文件。
参数:filename 是文件路径。
返回值:生存乐成返回 XML_SUCCESS,否则返回错误码。
  1. if (doc.SaveFile("output.xml") != XML_SUCCESS) {
  2.     std::cerr << "Failed to save XML file!" << std::endl;
  3. }
复制代码
1.3RootElement()

功能:获取 XML 文档的根元素。
返回值:指向根元素的指针,如果没有根元素返回 nullptr。
  1. XMLElement* root = doc.RootElement();
  2. if (!root) {
  3.     std::cerr << "No root element found!" << std::endl;
  4. } else {
  5.     std::cout << "Root element: " << root->Name() << std::endl;
  6. }
复制代码
1.4Parse(const char* xml)

功能:直接分析 XML 字符串。
参数:xml 是一个 XML 格式的字符串。
返回值:分析乐成返回 XML_SUCCESS,否则返回错误码。
  1. const char* xml = "<Root><Child>Text</Child></Root>";
  2. if (doc.Parse(xml) != XML_SUCCESS) {
  3.     std::cerr << "Failed to parse XML string!" << std::endl;
  4. }
  5. 示例
  6.         // 1. 基本解析
  7. XMLDocument doc;
  8. // 解析简单的XML字符串
  9. const char* xml = "<Root><Child>Hello</Child></Root>";
  10. if (doc.Parse(xml) == XML_SUCCESS) {
  11.     XMLElement* root = doc.FirstChildElement("Root");
  12.     XMLElement* child = root->FirstChildElement("Child");
  13.     const char* text = child->GetText();  // 获取 "Hello"
  14. }
  15. // 2. 解析带属性的XML
  16. const char* xmlWithAttr = R"(
  17.     <Person id="1" name="John">
  18.         <Age>30</Age>
  19.         <Address city="New York">
  20.             <Street>Broadway</Street>
  21.         </Address>
  22.     </Person>
  23. )";
  24. if (doc.Parse(xmlWithAttr) == XML_SUCCESS) {
  25.     XMLElement* person = doc.FirstChildElement("Person");
  26.     const char* name = person->Attribute("name");  // 获取 "John"
  27.    
  28.     XMLElement* address = person->FirstChildElement("Address");
  29.     const char* city = address->Attribute("city");  // 获取 "New York"
  30. }
  31. // 3. 解析列表数据
  32. const char* xmlList = R"(
  33.     <Inventory>
  34.         <Item id="1" name="Apple" price="0.5"/>
  35.         <Item id="2" name="Banana" price="0.3"/>
  36.         <Item id="3" name="Orange" price="0.4"/>
  37.     </Inventory>
  38. )";
  39. class InventoryParser {
  40. public:
  41.     struct Item {
  42.         int id;
  43.         string name;
  44.         double price;
  45.     };
  46.     static vector<Item> parseItems(const char* xml) {
  47.         vector<Item> items;
  48.         XMLDocument doc;
  49.         
  50.         if (doc.Parse(xml) == XML_SUCCESS) {
  51.             XMLElement* inventory = doc.FirstChildElement("Inventory");
  52.             for (XMLElement* elem = inventory->FirstChildElement("Item");
  53.                  elem != nullptr;
  54.                  elem = elem->NextSiblingElement("Item")) {
  55.                
  56.                 Item item;
  57.                 item.id = elem->IntAttribute("id");
  58.                 item.name = elem->Attribute("name");
  59.                 item.price = elem->DoubleAttribute("price");
  60.                 items.push_back(item);
  61.             }
  62.         }
  63.         return items;
  64.     }
  65. };
  66. // 4. 解析嵌套结构
  67. const char* xmlNested = R"(
  68.     <Company>
  69.         <Department name="Engineering">
  70.             <Employee id="1">
  71.                 <Name>John Doe</Name>
  72.                 <Position>Developer</Position>
  73.                 <Skills>
  74.                     <Skill>C++</Skill>
  75.                     <Skill>Python</Skill>
  76.                 </Skills>
  77.             </Employee>
  78.         </Department>
  79.     </Company>
  80. )";
  81. class CompanyParser {
  82. public:
  83.     static void parseEmployee(XMLElement* empElement) {
  84.         string name = empElement->FirstChildElement("Name")->GetText();
  85.         string position = empElement->FirstChildElement("Position")->GetText();
  86.         
  87.         vector<string> skills;
  88.         XMLElement* skillsElem = empElement->FirstChildElement("Skills");
  89.         for (XMLElement* skill = skillsElem->FirstChildElement("Skill");
  90.              skill != nullptr;
  91.              skill = skill->NextSiblingElement("Skill")) {
  92.             skills.push_back(skill->GetText());
  93.         }
  94.     }
  95. };
  96. // 5. 错误处理
  97. class XMLParser {
  98. public:
  99.     static bool parseWithErrorHandling(const char* xml) {
  100.         XMLDocument doc;
  101.         XMLError err = doc.Parse(xml);
  102.         
  103.         switch (err) {
  104.             case XML_SUCCESS:
  105.                 return true;
  106.             case XML_ERROR_FILE_NOT_FOUND:
  107.                 cerr << "XML file not found!" << endl;
  108.                 break;
  109.             case XML_ERROR_PARSING_ELEMENT:
  110.                 cerr << "Error parsing element!" << endl;
  111.                 break;
  112.             case XML_ERROR_PARSING_ATTRIBUTE:
  113.                 cerr << "Error parsing attribute!" << endl;
  114.                 break;
  115.             default:
  116.                 cerr << "Unknown XML error!" << endl;
  117.         }
  118.         return false;
  119.     }
  120. };
  121. // 6. 配置文件解析
  122. const char* configXml = R"(
  123.     <Config>
  124.         <Database>
  125.             <Host>localhost</Host>
  126.             <Port>3306</Port>
  127.             <Username>root</Username>
  128.             <Password>secret123</Password>
  129.         </Database>
  130.         <Server>
  131.             <Port>8080</Port>
  132.             <MaxConnections>100</MaxConnections>
  133.         </Server>
  134.     </Config>
  135. )";
  136. class ConfigParser {
  137. public:
  138.     struct DBConfig {
  139.         string host;
  140.         int port;
  141.         string username;
  142.         string password;
  143.     };
  144.     struct ServerConfig {
  145.         int port;
  146.         int maxConnections;
  147.     };
  148.     static pair<DBConfig, ServerConfig> parseConfig(const char* xml) {
  149.         XMLDocument doc;
  150.         DBConfig db;
  151.         ServerConfig server;
  152.         
  153.         if (doc.Parse(xml) == XML_SUCCESS) {
  154.             XMLElement* config = doc.FirstChildElement("Config");
  155.             
  156.             // 解析数据库配置
  157.             XMLElement* dbElem = config->FirstChildElement("Database");
  158.             db.host = dbElem->FirstChildElement("Host")->GetText();
  159.             db.port = atoi(dbElem->FirstChildElement("Port")->GetText());
  160.             db.username = dbElem->FirstChildElement("Username")->GetText();
  161.             db.password = dbElem->FirstChildElement("Password")->GetText();
  162.             
  163.             // 解析服务器配置
  164.             XMLElement* serverElem = config->FirstChildElement("Server");
  165.             server.port = atoi(serverElem->FirstChildElement("Port")->GetText());
  166.             server.maxConnections = atoi(serverElem->FirstChildElement("MaxConnections")->GetText());
  167.         }
  168.         
  169.         return {db, server};
  170.     }
  171. };
复制代码
2.元素利用

2.1 FirstChildElement(const char* name = nullptr)

功能:获取元素的第一个子元素。如果 name 参数不为空,则返回名称匹配的第一个子元素。
参数:name 是可选参数,表现子元素的名称。
返回值:指向第一个子元素的指针,如果没有找到返回 nullptr。
  1. XMLElement* firstChild = root->FirstChildElement();
  2. if (firstChild) {
  3.     std::cout << "First child element: " << firstChild->Name() << std::endl;
  4. }
复制代码
2.2 NextSiblingElement(const char* name = nullptr)

功能:获取当前元素的下一个同级元素。如果 name 参数不为空,则返回名称匹配的下一个同级元素。
参数:name 是可选参数,表现同级元素的名称。
返回值:指向下一个同级元素的指针,如果没有找到返回 nullptr。
  1. for (XMLElement* child = root->FirstChildElement(); child != nullptr; child = child->NextSiblingElement()) {
  2.     std::cout << "Sibling element: " << child->Name() << std::endl;
  3. }
复制代码
2.3 SetName(const char* name)

功能:设置元素的名称。
参数:name 是新名称的字符串。
  1. element->SetName("NewName");
复制代码
2.4 DeleteChild(XMLElement* child)

功能:删除当前元素的指定子元素。
参数:child 是必要删除的子元素指针。
  1. root->DeleteChild(child);
复制代码
3. 属性利用

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

功能:设置元素的字符串属性。
参数:name 是属性名,value 是属性值。
  1. element->SetAttribute("key", "value");
复制代码
3.2 Attribute(const char* name)

功能:获取元素指定名称的属性值。
参数:name 是属性名。
返回值:指向属性值的字符串指针,如果属性不存在返回 nullptr。
  1. const char* attrValue = element->Attribute("key");
  2. if (attrValue) {
  3.     std::cout << "Attribute value: " << attrValue << std::endl;
  4. }
复制代码
3.3 DeleteAttribute(const char* name)

功能:删除元素指定名称的属性。
参数:name 是属性名。
  1. element->DeleteAttribute("key");
复制代码
4. 文本利用

4.1 SetText(const char* text)

功能:设置元素的文本内容。
参数:text 是字符串,表现要设置的文本内容。
  1. element->SetText("This is text content");
复制代码
4.2 GetText()

功能:获取元素的文本内容。
返回值:指向文本内容的字符串指针,如果没有文本内容返回 nullptr。
  1. const char* text = element->GetText();
  2. if (text) {
  3.     std::cout << "Text content: " << text << std::endl;
  4. }
复制代码
5. 新建元素和节点

5.1 NewElement(const char* name)

功能:创建一个新的元素。
参数:name 是新元素的名称。
返回值:指向新创建的元素的指针。
  1. XMLElement* newElement = doc.NewElement("NewElement");
复制代码
5.2 InsertFirstChild(XMLNode* child)

功能:将一个子元素插入到当前元素的最前面。
参数:child 是要插入的子元素指针。
  1. root->InsertFirstChild(newElement);
复制代码
5.3 InsertEndChild(XMLNode* child)

功能:将一个子元素插入到当前元素的末端。
参数:child 是要插入的子元素指针。
  1. root->InsertEndChild(newElement);
复制代码
6. 错误处置惩罚

6.1 ErrorID()

功能:返回文档的错误代码。
  1. if (doc.ErrorID() != XML_SUCCESS) {
  2.     std::cerr << "Error occurred: " << doc.ErrorID() << std::endl;
  3. }
复制代码
6.2ErrorStr()

功能:返回错误信息字符串。
  1. if (doc.ErrorID() != XML_SUCCESS) {
  2.     std::cerr << "Error details: " << doc.ErrorStr() << std::endl;
  3. }
复制代码
附录:XML文件格式


  • XML的根本结构

    • 声明部分
      XML文件的开头是声明,表现XML的版本和编码格式
    1. <?xml version="1.0" encoding="UTF-8"?>
    复制代码
      

    • 根元素
      XML文件必须有且只有一个根元素,全部其他内容都嵌套在根元素中
    1. <root>
    2.     <!-- 子元素 -->
    3. </root>
    复制代码
      

    • 元素
      元素是XML的根本构成单元,通常由开始标签和竣事标签构成
    1. <element>内容</element>
    复制代码
    1. - 可以嵌套子元素。
    2. - 可以携带属性
    复制代码
    1. <element attribute="value">内容</element>
    复制代码
    1. - 属性
    复制代码
    属性是形貌元素的附加信息,格式为key=“value”
    1. <book id="1" author="Author Name">Book Title</book>
    复制代码
    1. - 注释
    复制代码
    表明用于添加阐明性笔墨
    1. <!-- 这是一个注释 -->
    复制代码
    1. - 文本内容
    复制代码
    1. <name>张三</name>
    复制代码

  • XML规则
    - 标签匹配
    标签匹配:每个开始标签必须有对应的竣事标签
    1. <name>张三</name>
    复制代码
    单标签情势必要利用斜杠
    - 区分巨细写
    XML区分巨细写,比方和是差异的标签。
    - 属性
    值必须利用引号:可以是单引号或双引号
    1. <person gender="male"></person>
    复制代码
  • 转义字符
特别字符转义符示例代码输出结果&&<text>AT&T</text><text>AT&T</text><<<text>1 < 2</text><text>1 < 2</text>>><text>3 > 2</text><text>3 > 2</text>'&apos;<attribute value='John&apos;s book' /><attribute value='John's book' />""<attribute value="He said "Hello"" /><attribute value="He said "Hello"" />定名空间


  • 由来


  • XML 中,标署名是自由界说的,差异的 XML 文档中大概会出现雷同名称的标签。如果多个 XML 文件必要归并或扩展,很轻易发生定名辩说。定名空间为标签和属性分配一个唯一的标识符,办理了辩说标题。
  • 定名空间现实上是一个唯一的 URI(Uniform Resource Identifier),通常是一个 URL(但不必要真实存在)。它标识某一组标签属于特定的上下文。

  • 语法


  • 默认定名空间
  1. <root xmlns="http://example.com/namespace">
  2.     <child>Content</child>
  3. </root>
  4. <!--作用范围:没有前缀的所有标签(<root> 和 <child>)都属于这个命名空间。-->
复制代码


  • 带前缀的定名空间
  1. <root xmlns:ns="http://example.com/namespace">
  2.     <ns:child>Content</ns:child>
  3. </root>
  4. <!--xmlns:ns="http://example.com/namespace" 声明了带前缀的命名空间-->
  5. <!--标签 <ns:child> 使用了 ns 前缀,表示它属于命名空间 http://example.com/namespace-->
  6. <!--作用范围:只有使用了 ns: 前缀的标签。-->
复制代码


  • 办理的标题
  1. <person xmlns:p="http://example.com/person">
  2.     <p:name>John</p:name>
  3. </person>
  4. <product xmlns:prod="http://example.com/product">
  5.     <prod:name>Smartphone</prod:name>
  6. </product>
复制代码
模式位置

简朴的XML文件

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- 这是一个简朴的 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文件

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- 复杂 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>[email protected]</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>
复制代码
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表