0

I have an XML file which is being used for storing camera parameters which will get updated in response to changes from the UI. With RapidXML, I can read the XML file, all elements & their attribute values. However, when I try to update the value of an attribrute/ element & save it, the file does not reflect the new value but shows the old value. I tried to test this concept on a small XML file like this

<?xml version="1.0" encoding="UTF-8"?>
<note>
    <to>Kum</to>
    <from>Jani</from>
    <heading>Reminder</heading>
    <body>Dont forget me this weekend!</body>
</note>

This is just a simple sample file with no attributes> And this is the code I have.

rapidxml::xml_document<> doc;
std::fstream file("TestFile.xml",std::ios::in|std::ios::out);

std::stringstream bufferStream;
bufferStream << file.rdbuf();
std::string content(bufferStream.str());
std::vector<char> buffer(content.begin(), content.end());
buffer.push_back('\0');
doc.parse<rapidxml::parse_no_data_nodes>(&content[0]);

rapidxml::xml_node<>* rootNode = doc.first_node();
std::cout <<"<"<< rootNode->name() <<">" << "\n";
rapidxml::xml_node<>* firstNode = rootNode->first_node("to");
std::cout << "<"<<firstNode->name()<<">" <<firstNode->value()<< "\n";

rapidxml::xml_node<> *real_thing = rootNode->first_node("from");

if (real_thing != nullptr)                              
{
    real_thing->value("yuck");  // now that should work
    std::cout << real_thing->name() << real_thing->value() << "\n";
}

Here on is where I am confused. How do I save this change back to the original xml file. If I do,

file << bufferStream.str();

It not only does not save the new value, but seems to append the entire XML DOM instead of replacing the original element value. If some one can share a little snippet on how to go about this objective, I would appreciate that. I spent the entire day looking through the documentation but also didn't understand the flags that get passed to the parse function.

Thanks

1 Answers1

1

RapidXML holds an internal representation of the document structure, using pointers to the text data held in the std::vector<char> that you passed to parse.

When you modify the 'value of a node you're really just changing a pointer in the internal structure. You need to get back to a string using functions in rapidxml_print.hpp, which includes an operator for writing to a stream.

file << doc;

Why does it append? Because after your read the data, the stream position is at the END of the file. You could reset to the beginning using file.seek(0) but this won't truncate the file if your new data is shorter than the old.

The best approach is simply to write the data out to a new fstream, rather than trying to have one open for simultaneous read and write.

Also see here for some much tidier and faster ways to parse a file with RapidXML. How to parse the XML file in RapidXML

Roddy
  • 66,617
  • 42
  • 165
  • 277