I'm parsing a XML
file from a string
.
My node Id
is bar
, and I want to change it to foo
and then write to file.
After writing to file, the file still have the bar
, and not the foo
.
#include "rapidxml.hpp"
#include "rapidxml_print.hpp"
void main()
{
std::string newXml = "<?xml version=\"1.0\" encoding=\"UTF - 8\"?><Parent><FileId>fileID</FileId><IniVersion>2.0.0</IniVersion><Child><Id>bar</Id></Child></Parent>";
xml_document<> doc;
xml_node<> * root_node;
std::string str = newXml;
std::vector<char> buffer(str.begin(), str.end());
buffer.push_back('\0');
doc.parse<0>(&buffer[0]);
root_node = doc.first_node("Parent");
xml_node<> * node = root_node->first_node("Child");
xml_node<> * xml = node->first_node("Id");
xml->value("foo"); // I want to change my id from bar to foo!!!!
std::ofstream outFile("output.xml");
outFile << doc; // after I write to file, I still see the ID as bar
}
What am I missing here?
The issue is in the layout of data. Under node_element
node xml
there is yet another node_data
node that contains "bar"
.
Your posted code also does not compile. Here I made your code to compile and did show how to fix it:
#include <vector>
#include <iostream>
#include "rapidxml.hpp"
#include "rapidxml_print.hpp"
int main()
{
std::string newXml = "<?xml version=\"1.0\" encoding=\"UTF - 8\"?><Parent><FileId>fileID</FileId><IniVersion>2.0.0</IniVersion><Child><Id>bar</Id></Child></Parent>";
rapidxml::xml_document<> doc;
std::string str = newXml;
std::vector<char> buffer(str.begin(), str.end());
buffer.push_back('\0');
doc.parse<0>(&buffer[0]);
rapidxml::xml_node<>* root_node = doc.first_node("Parent");
rapidxml::xml_node<>* node = root_node->first_node("Child");
rapidxml::xml_node<>* xml = node->first_node("Id");
// xml->value("foo"); // does change something that isn't output!!!!
rapidxml::xml_node<> *real_thing = xml->first_node();
if (real_thing != nullptr // these checks just demonstrate that
&& real_thing->next_sibling() == nullptr // it is there and how it is located
&& real_thing->type() == rapidxml::node_data) // when element does contain text data
{
real_thing->value("yuck"); // now that should work
}
std::cout << doc; // lets see it
}
And so it outputs:
<Parent>
<FileId>fileID</FileId>
<IniVersion>2.0.0</IniVersion>
<Child>
<Id>yuck</Id>
</Child>
</Parent>
See? Note that how data is laid out during parse depends on flags that you give to parse. For example if you first put doc.parse<rapidxml::parse_fastest>
then parser will not create such node_data
nodes and then changing node_element
data (like you first tried) will work (and what I did above will not). Read the details from manual.