You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用tinyxml2在C++中删除XML指定子元素失败求助

问题排查:tinyxml2删除XML元素无效果

问题背景

使用tinyxml2处理XML文件,目标是删除最后3个<boy>元素,但执行代码后文件无任何变化。

XML文件结构

<city>
    <school>
        <class>
            <boy name="Jose">
                <age>14</age>
            </boy>
            <boy name="Jim">
                <age>15</age>
            </boy>
            <boy name="Mike">
                <age>13</age>
            </boy>
            <boy name="Ben">
                <age>14</age>
            </boy>
            <boy name="Eddy">
                <age>14</age>
            </boy>
            <boy name="Jim">
                <age>16</age>
            </boy>
        </class>
    </school>
</city>

问题代码

void cropData(char *titlecity)
{
    tinyxml2::XMLNode *city = nullptr;
    tinyxml2::XMLNode *school = nullptr;
    tinyxml2::XMLNode *class = nullptr;
    tinyxml2::XMLError result;

    tinyxml2::XMLDocument doccity;
    doccity.LoadFile(titlecity);
    tinyxml2::XMLNode* root = doccity.FirstChild();
    if(root == nullptr)
        std::cout << "Cannot open file" << std::endl;

    city = doccity.FirstChildElement("city");
    assert(city);
    school = city->FirstChildElement("school");
    assert(school);
    class = school->FirstChildElement("class");
    assert(class);

    int i = 0;

    for (tinyxml2::XMLElement *boy = class->FirstChildElement("boy"); boy; boy = boy->NextSiblingElement("boy"))
    {
        if(i>3)
        {
            boy->Parent()->DeleteChild(boy);
        }
        i++;
    }

    doccity.SaveFile("DeleteAttribute_demo_file.txt");
}

问题分析

  1. 遍历中删除元素导致迭代失效:在for循环里直接删除当前boy元素后,boy->NextSiblingElement("boy")会因为节点已被销毁而无法正确获取下一个元素,遍历会提前终止,后续需要删除的元素不会被处理。
  2. 关键字冲突:class是C++的关键字,不能用作变量名,这会导致编译错误(若代码未实际编译通过,自然不会产生任何修改效果)。
  3. 边界条件错误:目标是删除最后3个元素(共6个<boy>),前3个需保留。代码中i>3的条件仅会删除索引为4、5的2个元素,遗漏了索引为3的元素,且逻辑不符合需求。

修正后的代码

#include <tinyxml2.h>
#include <cassert>
#include <iostream>
#include <vector>

void cropData(char *titlecity)
{
    tinyxml2::XMLNode *city = nullptr;
    tinyxml2::XMLNode *school = nullptr;
    tinyxml2::XMLNode *classNode = nullptr; // 替换关键字class为合法变量名

    tinyxml2::XMLDocument doccity;
    // 增加文件加载错误检查
    tinyxml2::XMLError loadResult = doccity.LoadFile(titlecity);
    if (loadResult != tinyxml2::XML_SUCCESS) {
        std::cout << "Cannot open file, error code: " << loadResult << std::endl;
        return;
    }

    city = doccity.FirstChildElement("city");
    assert(city);
    school = city->FirstChildElement("school");
    assert(school);
    classNode = school->FirstChildElement("class");
    assert(classNode);

    // 先收集所有需要删除的节点,避免遍历中修改DOM结构导致的迭代问题
    std::vector<tinyxml2::XMLElement*> boysToDelete;
    int i = 0;
    for (tinyxml2::XMLElement *boy = classNode->FirstChildElement("boy"); boy; boy = boy->NextSiblingElement("boy"))
    {
        // 前3个元素保留(i=0,1,2),从第4个开始加入删除列表
        if (i >= 3) {
            boysToDelete.push_back(boy);
        }
        i++;
    }

    // 统一删除收集到的节点
    for (auto boy : boysToDelete) {
        classNode->DeleteChild(boy);
    }

    // 增加文件保存错误检查
    tinyxml2::XMLError saveResult = doccity.SaveFile("DeleteAttribute_demo_file.txt");
    if (saveResult != tinyxml2::XML_SUCCESS) {
        std::cout << "Failed to save file, error code: " << saveResult << std::endl;
    }
}

修正说明

  • 替换class变量名为classNode,规避C++关键字冲突。
  • 先收集需要删除的节点再统一删除,避免遍历过程中修改DOM结构导致的迭代异常。
  • 调整判断条件为i >= 3,确保删除最后3个<boy>元素。
  • 增加文件加载和保存的错误检查,便于排查IO问题。

内容的提问来源于stack exchange,提问作者janullo789

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 15:33:34