1

I'm using tinyxml2. I have xml file with many elements on one node. My xml file:

<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>

For example, I have to remove the last three boys. I wrote this, but it don't work.

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");
}

This code does not change file. I'm really sorry, if my english is bad.

janullo789
  • 41
  • 5

1 Answers1

1

You have two errors in that code. One is a syntax error and the other is a logical error.

The syntax error is that you can't name a variable "class" because "class" is a reserved word in C++.

The logical error is that your for loop is iterating over elements by incrementing using the element's NextSiblingElement getter function; however, once you delete an element its next element will no longer be valid.

See below:

void cropData(tinyxml2::XMLDocument& doccity)
{
    auto* city = doccity.FirstChildElement("city");
    auto* school = city->FirstChildElement("school");
    auto* class_ = school->FirstChildElement("class");
    int i = 0;
    auto* boy = class_->FirstChildElement("boy");
    while (boy != nullptr) {
        auto next = boy->NextSiblingElement("boy");
        if (i > 3) {
            boy->Parent()->DeleteChild(boy);
        }
        boy = next;
        ++i;
    }

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

int main() {

    static const char* xml =
        "<?xml version=\"1.0\"?>"
        "<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>";

    tinyxml2::XMLDocument doc;
    doc.Parse(xml);
    cropData(doc);
}
jwezorek
  • 8,592
  • 1
  • 29
  • 46
  • 2
    Thank you! In fact, I have a more extensive code and example with boys and class is only simplification, but thank you for pointing that out. I have repaired a loop with logical error and now all work great! – janullo789 Aug 16 '22 at 10:28