Search code examples
c++xmltinyxml

TinyXML insert at last position.


I have a xml file that looks something like this

<App>
    <FileLog>
        <recording id="1" name="filename1.mp3" date="123467" length="66" />
        <recording id="2" name="filename2.mp3" date="123345" length="66" />
        <recording id="3" name="filename3.mp3" date="123345" length="66" />
    </FileLog>
</App>

I'm trying to insert another recording element after the last recording element (the one with the highest id) using TinyXML.

My code is

string xml="C:/logs.xml";
TiXmlDocument doc(xml.c_str());
if(doc.LoadFile()) 
{
    doc.FirstChild("FileLog");
    TiXmlElement recording("recording");
    recording.SetAttribute("id",4);
    recording.SetAttribute("name","filenamex.mp3");
    recording.SetAttribute("date",436636);
    recording.SetAttribute("length",34);
    doc.InsertAfterChild(recording);
}
else cout << "error loading file" << endl;

if(doc.SaveFile(xml.c_str())){
    cout << "file saved succesfully.\n";

}
else cout << "error saving file" << endl;

I'm not getting my desired output. How can I get it to always input the element at the last position?


Solution

  • Well, based on the document, the first child of the document is App, not FileLog (you're also not storing the result). Something like the following should work:

    if (doc.LoadFile()) {
      TiXmlHandle docHandle(&doc);
      TiXmlElement* fileLog = docHandle.FirstChild("App").FirstChild("FileLog").ToElement();
    
      if (fileLog) {
        TiXmlElement recording("recording");
    
        recording.SetAttribute("id", 4);
        recording.SetAttribute("name", "filenamex.mp3");
        recording.SetAttribute("date", 436636);
        recording.SetAttribute("length", 34);
    
        fileLog->InsertEndChild(recording);
      }
    }
    

    Note that with TiXmlHandle, you don't need to worry about the existence of the children nodes in between - you just need to check at the end.