C++ TinyXML解析案例详解

半杯拿铁
半杯拿铁
发布时间:2026-10-16| 8人浏览过
原创

本文详细介绍如何使用C++开源库TinyXML解析和操作XML文件。通过提供从配置目录到具体增删改查操作的完整代码示例,帮助开发者快速上手并解决实际的配置文件解析需求。

TinyXML核心机制与类结构

TinyXML是一个基于DOM(文档对象模型)的轻量级XML解析库,适用于Windows和Linux平台。它通过将整个XML文档转化为内存中的树状结构,使开发者能够方便地遍历和处理数据。在该库的设计中,各种XML组件对应特定的C++类:

  • TiXmlBase:所有TinyXML类的基类。
  • TiXmlDocument:代表整个XML文档,用于加载文件或作为顶层容器。
  • TiXmlElement:对应XML中的元素(标签),支持获取属性、子节点等操作。
  • TiXmlNode:DOM结构中的节点基类,其他节点如评论(TiXmlComment)、文本(TiXmlText)均继承于此。
  • TiXmlAttribute:对应元素的属性,可通过链式调用获取下一个属性。
  • TiXmlDeclaration:处理声明部分,如<?xml version="1.0" ?>。

项目准备与编译环境

使用前需下载源码并整理目录结构。典型的工程组织方式如下所示,确保头文件、源码及示例代码位置清晰:

tinyxml/           //工作根目录
|-- include        //头文件根目录
|   |-- tinyxml    //tinyxml头文件,包括tinystr.h tinyxml.h
|-- src            //cpp源码文件根目录
    |-- tinyxml       //tinyxml源码文件夹,包括tinystr.cpp tinyxml.cpp tinyxmlerror.cpp tinyxmlparser.cpp
    |-- main.cpp   //主函数入口,包含调用示例代码
|-- conf            //示例XML配置文件目录
|-- makefile       //编译脚本

在代码中包含 #include "tinyxml.h" 即可开始使用,注意源码文件中包含的 .cpp 文件需一并编译。

读取与遍历XML文件

读取XML的核心步骤是创建文档对象并加载文件,随后通过链式调用 FirstChildElement() 和 NextSiblingElement() 实现树的遍历。以下示例展示如何读取学生信息并打印属性及子节点内容:

第1步:加载并验证XML文档

目的:建立内存中的DOM模型,确认文件加载成功。
动作:调用 doc.LoadFile() 并检查返回值。若失败则输出错误日志。
完成状态:doc.RootElement() 不再为空,可获取根节点。

第2步:遍历目标节点并提取数据

目的:定位特定层级的元素并读取其属性值与内部文本。
操作逻辑:

  1. 获取根元素后,逐级向下寻找子节点(如 School → Class → Student)。
  2. 使用 FirstAttribute() 配合循环 Next() 遍历当前节点的所有属性。
  3. 对于文本节点或子元素,使用 FirstChildElement() 获取第一个兄弟节点,再通过 Value() 获取标签名,GetText() 获取纯文本内容。
void readSchoolXml() {
    const char * xmlFile = "conf/school.xml";
    TiXmlDocument doc;                              
    if (doc.LoadFile(xmlFile)) {
        doc.Print();
    } else {
        cout << "can not parse xml conf/school.xml" << endl;
        return;
    }
    
    // 获取根节点 School
    TiXmlElement* rootElement = doc.RootElement();  
    // 获取第一层子节点 Class
    TiXmlElement* classElement = rootElement->FirstChildElement();  
    // 获取第二层子节点 Student
    TiXmlElement* studentElement = classElement->FirstChildElement();  
    
    // 遍历所有学生节点
    for (; studentElement != NULL; studentElement = studentElement->NextSiblingElement() ) {
        // 打印属性:name, number等
        TiXmlAttribute* attributeOfStudent = studentElement->FirstAttribute();  
        for (;attributeOfStudent != NULL; attributeOfStudent = attributeOfStudent->Next() ) {
            cout << attributeOfStudent->Name() << " : " << attributeOfStudent->Value() << std::endl;       
        }                                 

        // 遍历学生的子节点内容,如 email 和 address
        TiXmlElement* studentContactElement = studentElement->FirstChildElement();
        for (; studentContactElement != NULL; studentContactElement = studentContactElement->NextSiblingElement() ) {
            string contactType = studentContactElement->Value();
            string contactValue = studentContactElement->GetText();
            cout << contactType  << " : " << contactValue << std::endl;           
        }   
    } 
}

构建与写入新的XML文件

当需要生成新的XML时,需先在堆内存中分配节点对象,并通过 SetAttribute() 设置属性,使用 LinkEndChild() 将子节点挂载到父节点上。最后调用 SaveFile() 持久化保存。

void writeSchoolXml() {
    const char * xmlFile = "conf/school-write.xml"; 
    
    TiXmlDocument doc;  
    // 添加声明
    TiXmlDeclaration * decl = new TiXmlDeclaration("1.0", "", "");  
    
    // 构建层级:School > Class > Student
    TiXmlElement * schoolElement = new TiXmlElement( "School" );  
    TiXmlElement * classElement = new TiXmlElement( "Class" );  
    classElement->SetAttribute("name", "C++");

    // 创建第一个学生节点 stu1
    TiXmlElement * stu1Element = new TiXmlElement("Student");
    stu1Element->SetAttribute("name", "tinyxml");
    stu1Element->SetAttribute("number", "123");
    
    TiXmlElement * stu1EmailElement = new TiXmlElement("email");
    stu1EmailElement->LinkEndChild(new TiXmlText("tinyxml@163.com") );
    TiXmlElement * stu1AddressElement = new TiXmlElement("address");
    stu1AddressElement->LinkEndChild(new TiXmlText("中国"));
    stu1Element->LinkEndChild(stu1EmailElement);
    stu1Element->LinkEndChild(stu1AddressElement);

    // 创建第二个学生节点 stu2
    TiXmlElement * stu2Element = new TiXmlElement("Student");
    stu2Element->SetAttribute("name", "jsoncpp");
    stu2Element->SetAttribute("number", "456");
    
    TiXmlElement * stu2EmailElement = new TiXmlElement("email");
    stu2EmailElement->LinkEndChild(new TiXmlText("jsoncpp@163.com"));
    TiXmlElement * stu2AddressElement = new TiXmlElement("address");
    stu2AddressElement->LinkEndChild(new TiXmlText("美国"));
    stu2Element->LinkEndChild(stu2EmailElement);
    stu2Element->LinkEndChild(stu2AddressElement);

    // 组装树结构
    classElement->LinkEndChild(stu1Element);  
    classElement->LinkEndChild(stu2Element);  
    schoolElement->LinkEndChild(classElement);  
    
    // 加入文档并保存
    doc.LinkEndChild(decl);  
    doc.LinkEndChild(schoolElement); 
    doc.SaveFile(xmlFile);  
}

节点的修改与删除操作

在处理现有XML数据时,常涉及查找特定节点并进行更新或删除。操作前请注意指针的有效性判断。

查找并修改属性值

例如将 <mfid val="1234" /> 中的属性值修改。通过 IterateChildren() 可以逐个查找指定名称的子节点,找到后通过 ToElement() 转换为元素指针,再获取属性进行修改:

TiXmlNode* lpnode = NULL;
// 假设 tixml 为已加载的文档根节点或当前上下文
lpnode = tixml.RootElement()->IterateChildren("mfid",lpnode);
if(lpnode) { // 确保找到了该节点
    TiXmlAttribute* tiattr = lpnode->ToElement()->FirstAttribute();
    // 修改第一个属性的值为新的字符串
    tiattr->SetValue(mfid.c_str());
}

移除节点

从父节点A中移除子节点B,直接调用父节点的 RemoveChild() 方法:

TiXmlNode nodeA;
// 传入要删除的目标节点指针
nodeA.RemoveChild( removeThisNodePointer );

或者移除元素上的指定名称属性:

TiXmlAttribute attrA;
attrA.RemoveAttribute(const char * name);

替换节点

如果需要将一个节点整体替换为另一个不同的节点实例,可使用 ReplaceChild():

parent.ReplaceChild(old_node_ptr, new_node_instance);

以上就是C++使用TinyXML解析、读写、修改XML文件的详细内容,更多关于C++ TinyXML应用技巧的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。